LCOV - app.info - netwerk/cache/nsDiskCacheBinding.cpp

LCOV - code coverage report
| Current view: | directory - netwerk/cache - nsDiskCacheBinding.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 141 | 94 | 66.7 %
| Date: | 2012-04-21 | Functions: | 22 | 19 | 86.4 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  *
           3                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is nsDiskCacheBinding.cpp, released
          17                 :  * May 10, 2001.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * Netscape Communications Corporation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 2001
          22                 :  * the Initial Developer. All Rights Reserved.
          23                 :  *
          24                 :  * Contributor(s):
          25                 :  *   Patrick C. Beard <beard@netscape.com>
          26                 :  *   Gordon Sheridan  <gordon@netscape.com>
          27                 :  *
          28                 :  * Alternatively, the contents of this file may be used under the terms of
          29                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          30                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          32                 :  * of those above. If you wish to allow use of your version of this file only
          33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          34                 :  * use your version of this file under the terms of the MPL, indicate your
          35                 :  * decision by deleting the provisions above and replace them with the notice
          36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          37                 :  * the provisions above, a recipient may use your version of this file under
          38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          39                 :  *
          40                 :  * ***** END LICENSE BLOCK ***** */
          41                 :
          42                 : #include <limits.h>
          43                 :
          44                 : #include "nscore.h"
          45                 : #include "nsDiskCacheBinding.h"
          46                 : #include "nsCacheService.h"
          47                 :
          48                 :
          49                 :
          50                 : /******************************************************************************
          51                 :  *  static hash table callback functions
          52                 :  *
          53                 :  *****************************************************************************/
          54                 : struct HashTableEntry : PLDHashEntryHdr {
          55                 :     nsDiskCacheBinding *  mBinding;
          56                 : };
          57                 :
          58                 :
          59                 : static PLDHashNumber
          60            4464 : HashKey( PLDHashTable *table, const void *key)
          61                 : {
          62            4464 :     return (PLDHashNumber) NS_PTR_TO_INT32(key);
          63                 : }
          64                 :
          65                 :
          66                 : static bool
          67            1658 : MatchEntry(PLDHashTable *              /* table */,
          68                 :             const PLDHashEntryHdr *       header,
          69                 :             const void *                  key)
          70                 : {
          71            1658 :     HashTableEntry * hashEntry = (HashTableEntry *) header;
          72            1658 :     return (hashEntry->mBinding->mRecord.HashNumber() == (PLDHashNumber) NS_PTR_TO_INT32(key));
          73                 : }
          74                 :
          75                 : static void
          76               0 : MoveEntry(PLDHashTable *           /* table */,
          77                 :           const PLDHashEntryHdr *     src,
          78                 :           PLDHashEntryHdr       *     dst)
          79                 : {
          80               0 :     ((HashTableEntry *)dst)->mBinding = ((HashTableEntry *)src)->mBinding;
          81               0 : }
          82                 :
          83                 :
          84                 : static void
          85             828 : ClearEntry(PLDHashTable *      /* table */,
          86                 :            PLDHashEntryHdr *      header)
          87                 : {
          88             828 :     ((HashTableEntry *)header)->mBinding = nsnull;
          89             828 : }
          90                 :
          91                 :
          92                 : /******************************************************************************
          93                 :  *  Utility Functions
          94                 :  *****************************************************************************/
          95                 : nsDiskCacheBinding *
          96            3035 : GetCacheEntryBinding(nsCacheEntry * entry)
          97                 : {
          98            3035 :     return (nsDiskCacheBinding *) entry->Data();
          99                 : }
         100                 :
         101                 :
         102                 : /******************************************************************************
         103                 :  *  nsDiskCacheBinding
         104                 :  *****************************************************************************/
         105                 :
         106            1656 : NS_IMPL_THREADSAFE_ISUPPORTS0(nsDiskCacheBinding)
         107                 :
         108             828 : nsDiskCacheBinding::nsDiskCacheBinding(nsCacheEntry* entry, nsDiskCacheRecord * record)
         109                 :     :   mCacheEntry(entry)
         110                 :     ,   mStreamIO(nsnull)
         111             828 :     ,   mDeactivateEvent(nsnull)
         112                 : {
         113             828 :     NS_ASSERTION(record->ValidRecord(), "bad record");
         114             828 :     PR_INIT_CLIST(this);
         115             828 :     mRecord     = *record;
         116             828 :     mDoomed     = entry->IsDoomed();
         117             828 :     mGeneration = record->Generation();    // 0 == uninitialized, or data & meta using block files
         118             828 : }
         119                 :
         120            1656 : nsDiskCacheBinding::~nsDiskCacheBinding()
         121                 : {
         122             828 :     NS_ASSERTION(PR_CLIST_IS_EMPTY(this), "binding deleted while still on list");
         123             828 :     if (!PR_CLIST_IS_EMPTY(this))
         124               0 :         PR_REMOVE_LINK(this);       // XXX why are we still on a list?
         125                 :
         126                 :     // sever streamIO/binding link
         127             828 :     if (mStreamIO) {
         128             708 :         if (NS_FAILED(mStreamIO->ClearBinding()))
         129               0 :             nsCacheService::DoomEntry(mCacheEntry);
         130             708 :         NS_RELEASE(mStreamIO);
         131                 :     }
         132            3312 : }
         133                 :
         134                 : nsresult
         135             728 : nsDiskCacheBinding::EnsureStreamIO()
         136                 : {
         137             728 :     if (!mStreamIO) {
         138             708 :         mStreamIO = new nsDiskCacheStreamIO(this);
         139             708 :         if (!mStreamIO)  return NS_ERROR_OUT_OF_MEMORY;
         140             708 :         NS_ADDREF(mStreamIO);
         141                 :     }
         142             728 :     return NS_OK;
         143                 : }
         144                 :
         145                 :
         146                 : /******************************************************************************
         147                 :  *  nsDiskCacheBindery
         148                 :  *
         149                 :  *  Keeps track of bound disk cache entries to detect for collisions.
         150                 :  *
         151                 :  *****************************************************************************/
         152                 :
         153                 : PLDHashTableOps nsDiskCacheBindery::ops =
         154                 : {
         155                 :     PL_DHashAllocTable,
         156                 :     PL_DHashFreeTable,
         157                 :     HashKey,
         158                 :     MatchEntry,
         159                 :     MoveEntry,
         160                 :     ClearEntry,
         161                 :     PL_DHashFinalizeStub
         162                 : };
         163                 :
         164                 :
         165             175 : nsDiskCacheBindery::nsDiskCacheBindery()
         166             175 :     : initialized(false)
         167                 : {
         168             175 : }
         169                 :
         170                 :
         171             175 : nsDiskCacheBindery::~nsDiskCacheBindery()
         172                 : {
         173             175 :     Reset();
         174             175 : }
         175                 :
         176                 :
         177                 : nsresult
         178             236 : nsDiskCacheBindery::Init()
         179                 : {
         180             236 :     nsresult rv = NS_OK;
         181             236 :     initialized = PL_DHashTableInit(&table, &ops, nsnull, sizeof(HashTableEntry), 0);
         182                 :
         183             236 :     if (!initialized) rv = NS_ERROR_OUT_OF_MEMORY;
         184                 :
         185             236 :     return rv;
         186                 : }
         187                 :
         188                 : void
         189             411 : nsDiskCacheBindery::Reset()
         190                 : {
         191             411 :     if (initialized) {
         192             236 :         PL_DHashTableFinish(&table);
         193             236 :         initialized = false;
         194                 :     }
         195             411 : }
         196                 :
         197                 :
         198                 : nsDiskCacheBinding *
         199             828 : nsDiskCacheBindery::CreateBinding(nsCacheEntry *       entry,
         200                 :                                   nsDiskCacheRecord *  record)
         201                 : {
         202             828 :     NS_ASSERTION(initialized, "nsDiskCacheBindery not initialized");
         203            1656 :     nsCOMPtr<nsISupports> data = entry->Data();
         204             828 :     if (data) {
         205               0 :         NS_ERROR("cache entry already has bind data");
         206               0 :         return nsnull;
         207                 :     }
         208                 :
         209             828 :     nsDiskCacheBinding * binding = new nsDiskCacheBinding(entry, record);
         210             828 :     if (!binding)  return nsnull;
         211                 :
         212                 :     // give ownership of the binding to the entry
         213             828 :     entry->SetData(binding);
         214                 :
         215                 :     // add binding to collision detection system
         216             828 :     nsresult rv = AddBinding(binding);
         217             828 :     if (NS_FAILED(rv)) {
         218               0 :         entry->SetData(nsnull);
         219               0 :         return nsnull;
         220                 :     }
         221                 :
         222             828 :     return binding;
         223                 : }
         224                 :
         225                 :
         226                 : /**
         227                 :  *  FindActiveEntry :  to find active colliding entry so we can doom it
         228                 :  */
         229                 : nsDiskCacheBinding *
         230            1980 : nsDiskCacheBindery::FindActiveBinding(PRUint32  hashNumber)
         231                 : {
         232            1980 :     NS_ASSERTION(initialized, "nsDiskCacheBindery not initialized");
         233                 :     // find hash entry for key
         234                 :     HashTableEntry * hashEntry;
         235            1980 :     hashEntry = (HashTableEntry *) PL_DHashTableOperate(&table, (void*) hashNumber, PL_DHASH_LOOKUP);
         236            1980 :     if (PL_DHASH_ENTRY_IS_FREE(hashEntry)) return nsnull;
         237                 :
         238                 :     // walk list looking for active entry
         239               2 :     NS_ASSERTION(hashEntry->mBinding, "hash entry left with no binding");
         240               2 :     nsDiskCacheBinding * binding = hashEntry->mBinding;
         241               4 :     while (binding->mCacheEntry->IsDoomed()) {
         242               0 :         binding = (nsDiskCacheBinding *)PR_NEXT_LINK(binding);
         243               0 :         if (binding == hashEntry->mBinding)  return nsnull;
         244                 :     }
         245               2 :     return binding;
         246                 : }
         247                 :
         248                 :
         249                 : /**
         250                 :  *  AddBinding
         251                 :  *
         252                 :  *  Called from FindEntry() if we read an entry off of disk
         253                 :  *      - it may already have a generation number
         254                 :  *      - a generation number conflict is an error
         255                 :  *
         256                 :  *  Called from BindEntry()
         257                 :  *      - a generation number needs to be assigned
         258                 :  */
         259                 : nsresult
         260             828 : nsDiskCacheBindery::AddBinding(nsDiskCacheBinding * binding)
         261                 : {
         262             828 :     NS_ENSURE_ARG_POINTER(binding);
         263             828 :     NS_ASSERTION(initialized, "nsDiskCacheBindery not initialized");
         264                 :
         265                 :     // find hash entry for key
         266                 :     HashTableEntry * hashEntry;
         267                 :     hashEntry = (HashTableEntry *) PL_DHashTableOperate(&table,
         268             828 :                                                         (void*) binding->mRecord.HashNumber(),
         269             828 :                                                         PL_DHASH_ADD);
         270             828 :     if (!hashEntry) return NS_ERROR_OUT_OF_MEMORY;
         271                 :
         272             828 :     if (hashEntry->mBinding == nsnull) {
         273             828 :         hashEntry->mBinding = binding;
         274             828 :         if (binding->mGeneration == 0)
         275             825 :             binding->mGeneration = 1;   // if generation uninitialized, set it to 1
         276                 :
         277             828 :         return NS_OK;
         278                 :     }
         279                 :
         280                 :
         281                 :     // insert binding in generation order
         282               0 :     nsDiskCacheBinding * p  = hashEntry->mBinding;
         283               0 :     bool     calcGeneration = (binding->mGeneration == 0);  // do we need to calculate generation?
         284               0 :     if (calcGeneration)  binding->mGeneration = 1;          // initialize to 1 if uninitialized
         285               0 :     while (1) {
         286                 :
         287               0 :         if (binding->mGeneration < p->mGeneration) {
         288                 :             // here we are
         289               0 :             PR_INSERT_BEFORE(binding, p);
         290               0 :             if (hashEntry->mBinding == p)
         291               0 :                 hashEntry->mBinding = binding;
         292               0 :             break;
         293                 :         }
         294                 :
         295               0 :         if (binding->mGeneration == p->mGeneration) {
         296               0 :             if (calcGeneration)  ++binding->mGeneration;    // try the next generation
         297                 :             else {
         298               0 :                 NS_ERROR("### disk cache: generations collide!");
         299               0 :                 return NS_ERROR_UNEXPECTED;
         300                 :             }
         301                 :         }
         302                 :
         303               0 :         p = (nsDiskCacheBinding *)PR_NEXT_LINK(p);
         304               0 :         if (p == hashEntry->mBinding) {
         305                 :             // end of line: insert here or die
         306               0 :             p = (nsDiskCacheBinding *)PR_PREV_LINK(p);  // back up and check generation
         307               0 :             if (p->mGeneration == 255) {
         308               0 :                 NS_WARNING("### disk cache: generation capacity at full");
         309               0 :                 return NS_ERROR_UNEXPECTED;
         310                 :             }
         311               0 :             PR_INSERT_BEFORE(binding, hashEntry->mBinding);
         312               0 :             break;
         313                 :         }
         314                 :     }
         315               0 :     return NS_OK;
         316                 : }
         317                 :
         318                 :
         319                 : /**
         320                 :  *  RemoveBinding :  remove binding from collision detection on deactivation
         321                 :  */
         322                 : void
         323             828 : nsDiskCacheBindery::RemoveBinding(nsDiskCacheBinding * binding)
         324                 : {
         325             828 :     NS_ASSERTION(initialized, "nsDiskCacheBindery not initialized");
         326             828 :     if (!initialized)   return;
         327                 :
         328                 :     HashTableEntry * hashEntry;
         329             828 :     void *           key = (void *)binding->mRecord.HashNumber();
         330                 :
         331                 :     hashEntry = (HashTableEntry*) PL_DHashTableOperate(&table,
         332                 :                                                        (void*) key,
         333             828 :                                                        PL_DHASH_LOOKUP);
         334             828 :     if (!PL_DHASH_ENTRY_IS_BUSY(hashEntry)) {
         335               0 :         NS_WARNING("### disk cache: binding not in hashtable!");
         336               0 :         return;
         337                 :     }
         338                 :
         339             828 :     if (binding == hashEntry->mBinding) {
         340             828 :         if (PR_CLIST_IS_EMPTY(binding)) {
         341                 :             // remove this hash entry
         342                 :             (void) PL_DHashTableOperate(&table,
         343             828 :                                         (void*) binding->mRecord.HashNumber(),
         344             828 :                                         PL_DHASH_REMOVE);
         345             828 :             return;
         346                 :
         347                 :         } else {
         348                 :             // promote next binding to head, and unlink this binding
         349               0 :             hashEntry->mBinding = (nsDiskCacheBinding *)PR_NEXT_LINK(binding);
         350                 :         }
         351                 :     }
         352               0 :     PR_REMOVE_AND_INIT_LINK(binding);
         353                 : }
         354                 :
         355                 :
         356                 : /**
         357                 :  *  ActiveBinding : PLDHashTable enumerate function to verify active bindings
         358                 :  */
         359                 :
         360                 : PLDHashOperator
         361               0 : ActiveBinding(PLDHashTable *    table,
         362                 :               PLDHashEntryHdr * hdr,
         363                 :               PRUint32          number,
         364                 :               void *            arg)
         365                 : {
         366               0 :     nsDiskCacheBinding * binding = ((HashTableEntry *)hdr)->mBinding;
         367               0 :     NS_ASSERTION(binding, "### disk cache binding = nsnull!");
         368                 :
         369               0 :     nsDiskCacheBinding * head = binding;
         370               0 :     do {
         371               0 :         if (binding->IsActive()) {
         372               0 :            *((bool *)arg) = true;
         373               0 :             return PL_DHASH_STOP;
         374                 :         }
         375                 :
         376               0 :         binding = (nsDiskCacheBinding *)PR_NEXT_LINK(binding);
         377                 :     } while (binding != head);
         378                 :
         379               0 :     return PL_DHASH_NEXT;
         380                 : }
         381                 :
         382                 :
         383                 : /**
         384                 :  *  ActiveBindings : return true if any bindings have open descriptors
         385                 :  */
         386                 : bool
         387              61 : nsDiskCacheBindery::ActiveBindings()
         388                 : {
         389              61 :     NS_ASSERTION(initialized, "nsDiskCacheBindery not initialized");
         390              61 :     if (!initialized) return false;
         391                 :
         392              61 :     bool    activeBinding = false;
         393              61 :     PL_DHashTableEnumerate(&table, ActiveBinding, &activeBinding);
         394                 :
         395              61 :     return activeBinding;
         396                 : }

Generated by: LCOV version 1.7