Beispiel #1
0
static TimerEvent *CreateTimer(
    PRIntervalTime timeout,
    void (*func)(void *),
    void *arg)
{
    TimerEvent *timer;
    PRCList *links, *tail;
    TimerEvent *elem;

    timer = PR_NEW(TimerEvent);
    if (NULL == timer)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return timer;
    }
    timer->absolute = PR_IntervalNow() + timeout;
    timer->func = func;
    timer->arg = arg;
    timer->ref_count = 2;
    PR_Lock(tm_vars.ml);
    tail = links = PR_LIST_TAIL(&tm_vars.timer_queue);
    while (links->prev != tail)
    {
        elem = TIMER_EVENT_PTR(links);
        if ((PRInt32)(timer->absolute - elem->absolute) >= 0)
        {
            break;
        }
        links = links->prev;
    }
    PR_INSERT_AFTER(&timer->links, links);
    PR_NotifyCondVar(tm_vars.new_timer);
    PR_Unlock(tm_vars.ml);
    return timer;
}
Beispiel #2
0
void
ssl_DestroyCipherSpecs(PRCList *list)
{
    while (!PR_CLIST_IS_EMPTY(list)) {
        ssl3CipherSpec *spec = (ssl3CipherSpec *)PR_LIST_TAIL(list);
        ssl_FreeCipherSpec(spec);
    }
}
Beispiel #3
0
void
ssl3_DestroyRemoteExtensions(PRCList *list)
{
    PRCList *cur_p;

    while (!PR_CLIST_IS_EMPTY(list)) {
        cur_p = PR_LIST_TAIL(list);
        PR_REMOVE_LINK(cur_p);
        PORT_Free(cur_p);
    }
}
NSFC_RecordEntryHit(NSFCCache cache, NSFCEntry entry)
{
    PR_ASSERT(entry->refcnt >= 1);

    entry->hitcnt++;

    /*
     * If existing entries can be recycled for new files, indicate that
     * this entry is active.
     */
    if (cache->cfg.replaceFiles == PR_TRUE) {
        /* Update the hit list order if this entry is in the hit list */
        PR_Lock(cache->hitLock);
        if (PR_LIST_HEAD(&entry->hit_list) != PR_LIST_TAIL(&entry->hit_list)) {
            if (cache->cfg.hitOrder == PR_TRUE) {
                /*
                 * If this entry is not at the head of the hit list,
                 * move it ahead of all entries with the same hitcnt.
                 */
                PRCList *prev;
                NSFCEntryImpl *pnep;

                for (prev = PR_PREV_LINK(&entry->hit_list);
                     prev != &cache->hit_list;
                     prev = PR_PREV_LINK(prev)) {

                    pnep = NSFCENTRYIMPL(prev);
                    if (pnep->hitcnt > entry->hitcnt) {
                        break; /* Our spot in the list */
                    }
                }

                /* Move the element up if necessary */
                if (prev != PR_PREV_LINK(&entry->hit_list)) {
                    PR_REMOVE_LINK(&entry->hit_list);
                    PR_INSERT_AFTER(&entry->hit_list, prev);
                }
            }
            else {
                /* Ignore hitcnt, keep list in strict MRU to LRU order */
                if (&entry->hit_list != PR_LIST_HEAD(&cache->hit_list)) {
                    PR_REMOVE_LINK(&entry->hit_list);
                    PR_INSERT_LINK(&entry->hit_list, &cache->hit_list);
                }
            }
        }
        PR_Unlock(cache->hitLock);
    }
}
bundleCacheEntry_t *
nsStringBundleService::insertIntoCache(nsIStringBundle* aBundle,
                                       nsCStringKey* aHashKey)
{
  bundleCacheEntry_t *cacheEntry;
  
  if (mBundleMap.Count() < MAX_CACHED_BUNDLES) {
    // cache not full - create a new entry
    
    void *cacheEntryArena;
    PL_ARENA_ALLOCATE(cacheEntryArena, &mCacheEntryPool, sizeof(bundleCacheEntry_t));
    cacheEntry = (bundleCacheEntry_t*)cacheEntryArena;
      
  } else {
    // cache is full
    // take the last entry in the list, and recycle it.
    cacheEntry = (bundleCacheEntry_t*)PR_LIST_TAIL(&mBundleCache);
      
    // remove it from the hash table and linked list
    NS_ASSERTION(mBundleMap.Exists(cacheEntry->mHashKey),
                 "Element will not be removed!");
#ifdef DEBUG_alecf
    NS_WARNING(nsPrintfCString(300,
                               "Booting %s to make room for %s\n",
                               cacheEntry->mHashKey->GetString(),
                               aHashKey->GetString()).get());
#endif
    mBundleMap.Remove(cacheEntry->mHashKey);
    PR_REMOVE_LINK((PRCList*)cacheEntry);

    // free up excess memory
    recycleEntry(cacheEntry);
  }
    
  // at this point we have a new cacheEntry that doesn't exist
  // in the hashtable, so set up the cacheEntry
  cacheEntry->mBundle = aBundle;
  NS_ADDREF(cacheEntry->mBundle);

  cacheEntry->mHashKey = (nsCStringKey*)aHashKey->Clone();
  
  // insert the entry into the cache and map, make it the MRU
  mBundleMap.Put(cacheEntry->mHashKey, cacheEntry);

  return cacheEntry;
}
NSAPI_PUBLIC ACLAttrGetter_t *
ACL_AttrGetterNext(ACLAttrGetterList_t *getters, ACLAttrGetter_t *last)
{
    ACLAttrGetter_t *head;
    ACLAttrGetter_t *next = 0;

    if (getters && *getters && last) {

        head = (ACLAttrGetter_t *)(*getters);
        if (head) {

            /* End of list? */
            if (last != (ACLAttrGetter_t *)PR_LIST_TAIL(&head->list)) {

                /* No, get next entry */
                next = (ACLAttrGetter_t *)PR_NEXT_LINK(&last->list);
            }
        }
    }

    return next;
}
nsPreflightCache::CacheEntry*
nsPreflightCache::GetEntry(nsIURI* aURI,
                           nsIPrincipal* aPrincipal,
                           PRBool aWithCredentials,
                           PRBool aCreate)
{
  nsCString key;
  if (!GetCacheKey(aURI, aPrincipal, aWithCredentials, key)) {
    NS_WARNING("Invalid cache key!");
    return nsnull;
  }

  CacheEntry* entry;

  if (mTable.Get(key, &entry)) {
    // Entry already existed so just return it. Also update the LRU list.

    // Move to the head of the list.
    PR_REMOVE_LINK(entry);
    PR_INSERT_LINK(entry, &mList);

    return entry;
  }

  if (!aCreate) {
    return nsnull;
  }

  // This is a new entry, allocate and insert into the table now so that any
  // failures don't cause items to be removed from a full cache.
  entry = new CacheEntry(key);
  if (!entry) {
    NS_WARNING("Failed to allocate new cache entry!");
    return nsnull;
  }

  NS_ASSERTION(mTable.Count() <= PREFLIGHT_CACHE_SIZE,
               "Something is borked, too many entries in the cache!");

  // Now enforce the max count.
  if (mTable.Count() == PREFLIGHT_CACHE_SIZE) {
    // Try to kick out all the expired entries.
    PRTime now = PR_Now();
    mTable.Enumerate(RemoveExpiredEntries, &now);

    // If that didn't remove anything then kick out the least recently used
    // entry.
    if (mTable.Count() == PREFLIGHT_CACHE_SIZE) {
      CacheEntry* lruEntry = static_cast<CacheEntry*>(PR_LIST_TAIL(&mList));
      PR_REMOVE_LINK(lruEntry);

      // This will delete 'lruEntry'.
      mTable.Remove(lruEntry->mKey);

      NS_ASSERTION(mTable.Count() == PREFLIGHT_CACHE_SIZE - 1,
                   "Somehow tried to remove an entry that was never added!");
    }
  }
  
  if (!mTable.Put(key, entry)) {
    // Failed, clean up the new entry.
    delete entry;

    NS_WARNING("Failed to add entry to the CORS preflight cache!");
    return nsnull;
  }

  PR_INSERT_LINK(entry, &mList);

  return entry;
}
NSFC_NewFilenameEntry(NSFCCache cip, const char *filename, 
                      PRUint32 hvalue, NSFCStatus &rfc)
{
    PRUint32 bucket = hvalue % cip->hsize;

    PR_ASSERT(cip);

    if (cip->state != NSFCCache_Active) {
        rfc = NSFC_DEADCACHE;
        return NULL;
    }

    rfc = NSFC_OK;

    /* Replace file cache entries once the cache fills up */
    if (_NSFC_IsTimeToReplace(cip)) {
        PR_Lock(cip->hitLock);
        if (!PR_CLIST_IS_EMPTY(&cip->hit_list)) {
            NSFCEntryImpl* nepDelete;
            PRUint32 bucketDelete;

            /* Get the LRU entry from the hit list and remember its bucket */
            PRCList *lru = PR_LIST_TAIL(&cip->hit_list);
            PR_ASSERT(lru);
            nepDelete = (NSFCEntryImpl*)((char*)lru - offsetof(NSFCEntryImpl,
                                                               hit_list));
            bucketDelete = nepDelete->hash % cip->hsize;
            PR_Unlock(cip->hitLock);

            /* Get access to the LRU entry's bucket */
            if (bucket != bucketDelete) {
                NSFC_RELEASEBUCKET(cip, bucket);
                NSFC_ACQUIREBUCKET(cip, bucketDelete);
            }

            /* Look for the LRU entry in the bucket */
            NSFCEntryImpl *nep;
            for (nep = cip->hname[bucketDelete]; nep; nep = nep->next) {
                if (nep == nepDelete) break;
            }
            if (nep == nepDelete) {
                /* The LRU entry is still around, mark it for deletion */
                NSFC_DeleteEntry(cip, nep, PR_TRUE);

                /* Increment count of replaced entries */
                PR_AtomicIncrement((PRInt32*)&cip->rplcCnt);
            }

            /* Get access to the new entry's bucket */
            if (bucket != bucketDelete) {
                NSFC_RELEASEBUCKET(cip, bucketDelete);
                NSFC_ACQUIREBUCKET(cip, bucket);
            }
        }
        else {
            PR_Unlock(cip->hitLock);
        }
    }

    /* Respect limit on number of cache entries */
    if (cip->curFiles >= cip->cfg.maxFiles) {
        cip->cacheFull = PR_TRUE;
        rfc = NSFC_NOSPACE;
        return NULL;
    }

    /* Get a file name entry */
    PR_Lock(cip->namefLock);
    NSFCEntryImpl *nep = cip->namefl;
    if (nep != NULL) {
        /* Found a file name entry on the free list */
        PR_ASSERT(nep->refcnt == 0);
        PR_ASSERT(!nep->fHashed);
        cip->namefl = nep->next;
    }
    PR_Unlock(cip->namefLock);
    if (nep == NULL) {
        /* Allocate a new file name entry */
        nep = (NSFCEntryImpl *)NSFC_Calloc(1, sizeof(*nep), cip);
        if (nep) {
            nep->seqno = 1;
        }
    }

    if (nep) {
        nep->filename = NSFC_Strdup(filename, cip);
        if (nep->filename) {
            /* Initialize entry */
            nep->next = NULL;
            nep->pdLock = PR_NewLock();
            nep->pdlist = NULL;
            nep->finfo.pr.type = PR_FILE_OTHER;
            nep->finfo.pr.size = 0;
            nep->finfo.pr.creationTime = 0;
            nep->finfo.pr.modifyTime = 0;
            PRIntervalTime now = ft_timeIntervalNow();
            nep->finfo.lastUpdate = now;
            nep->finfo.fileid[0] = hvalue;
            nep->finfo.fileid[1] = nep->seqno;
            nep->finfo.prerr = 0;
            nep->finfo.oserr = 0;
            nep->hash = hvalue;
            nep->hitcnt = 0;
            nep->refcnt = 1;
            nep->flags = 0;
            nep->fHashed = 1;
            nep->fDelete = 0;
            nep->fWriting = 0;

            /* Add entry to cache instance hash table */
            NSFC_ASSERTBUCKETHELD(cip, bucket);
            nep->next = cip->hname[bucket];
            cip->hname[bucket] = nep;
            PR_AtomicIncrement((PRInt32*)&cip->curFiles);

            /* Add entry to the hit list */
            PR_Lock(cip->hitLock);
            PR_INIT_CLIST(&nep->hit_list);
            if (cip->cfg.hitOrder == PR_TRUE) {
                /*
                 * Add this entry towards the end of the hit list,
                 * but ahead of other entries with a zero hit count.
                 */
                PRCList *prev;
                NSFCEntryImpl *pnep;

                for (prev = PR_LIST_TAIL(&cip->hit_list);
                     prev != &cip->hit_list;
                     prev = PR_PREV_LINK(prev)) {

                    pnep = NSFCENTRYIMPL(prev);
                    if (pnep->hitcnt > nep->hitcnt) {
                        break; /* Our spot in the list */
                    }
                }

                PR_INSERT_AFTER(&nep->hit_list, prev);
            }
            else {
                /* Put new entry at head of hit list */
                PR_INSERT_LINK(&nep->hit_list, &cip->hit_list);
            }
            PR_Unlock(cip->hitLock);

            PR_ASSERT(!nep->fDelete);
        }
        else {
            /* Failed, so return the entry to the free list */
            PR_Lock(cip->namefLock);
            nep->next = cip->namefl;
            cip->namefl = nep;
            nep = NULL;
            PR_Unlock(cip->namefLock);

            cip->cacheFull = PR_TRUE; /* file cache is full */
            rfc = NSFC_NOSPACE;
        }
    }
    else {
        cip->cacheFull = PR_TRUE; /* file cache is full */
        rfc = NSFC_NOSPACE;
    }

    /* Cache contents have been modified */
    cip->sig++;

    return nep;
}
static void
_NSFC_DestroyEntry(NSFCCache cip, NSFCEntryImpl *nep, PRBool delCntIt)
{
    NSFCEntryImpl **list;
    PRUint32 bucket = nep->hash % cip->hsize;
    int found = 0;

    PR_ASSERT(nep->refcnt == 0);
    PR_ASSERT(nep->fDelete);
    PR_ASSERT(nep->fHashed);

    ++nep->seqno;

    /* First remove the name entry from the hname hash table. */
    NSFC_ASSERTBUCKETHELD(cip, bucket);
    for (list = &cip->hname[bucket];
         *list; list = &(*list)->next) {
         if (*list == nep) {
             *list = nep->next;
             found = 1;
             break;
         }
    }
    PR_ASSERT(found == 1);
    nep->fHashed = 0;

    if (delCntIt == PR_TRUE) {
        PR_ASSERT(cip->busydCnt > 0);
        PR_AtomicDecrement((PRInt32 *)&cip->busydCnt);
    }

    /* No one but us should be able to see this entry */
    PR_ASSERT(nep->fDelete == PR_TRUE);
    PR_ASSERT(nep->fHashed == PR_FALSE);
    PR_ASSERT(nep->refcnt == 0);
    PR_ASSERT(PR_LIST_HEAD(&nep->hit_list) == PR_LIST_TAIL(&nep->hit_list));

    /* Free cached content */
    if (nep->flags & NSFCENTRY_HASCONTENT) {
        NSFC_MD_FreeContent(cip, nep);
    }

    /* Handle notifications for any associated private data */
    NSFCPrivateData *pdenext;
    NSFCPrivateData *pde;
    for (pde = nep->pdlist; pde; pde = pdenext) {
        pdenext = pde->next;
        if (pde->key->delfn) {
            pde->key->delfn(cip, nep->filename, pde->key, pde->pdata);
        }
        NSFC_Free(pde, sizeof(*pde), cip);
    }

    /* Destroy private data lock */
    if (nep->pdLock) {
        PR_DestroyLock(nep->pdLock);
        nep->pdLock = NULL;
    }

    /* Free filename string from entry, if any */
    if (nep->filename) {
        NSFC_FreeStr(nep->filename, cip);
        nep->filename = NULL;
    }

    /* Return the file name entry to the free list */
    PR_Lock(cip->namefLock);
    nep->next = cip->namefl;
    cip->namefl = nep;
    PR_Unlock(cip->namefLock);

    /* Finally decrement the number of entries used */
    if (!PR_AtomicDecrement((PRInt32*)&cip->curFiles)) {
        /* Wake anyone waiting for this final entry to go away */
        NSFC_RELEASEBUCKET(cip, bucket);
        NSFC_EnterCacheMonitor(cip);
        NSFC_ExitCacheMonitor(cip);
        NSFC_ACQUIREBUCKET(cip, bucket);
    }

    /* Cache contents have been modified */
    cip->sig++;
}
static NSFCStatus
_NSFC_DeleteEntry(NSFCCache cache, NSFCEntryImpl *nep, 
                  PRBool hasBucketLock, PRBool delCntIt, PRBool outdCntIt)
{
    NSFCStatus rfc = NSFC_OK;

    PR_ASSERT(nep);

    /* Get access to nep's bucket if caller doesn't have it already */
    PRUint32 bucket;
    if (hasBucketLock == PR_FALSE) {
        if (nep->fDelete) {
            return rfc;
        }
        bucket = nep->hash % cache->hsize;
        NSFC_ACQUIREBUCKET(cache, bucket);
    } else {
        NSFC_ASSERTBUCKETHELD(cache, nep->hash % cache->hsize);
    }

    /* If nep hasn't already been marked for deletion... */
    if (!nep->fDelete) {

        /* Remove nep from the hit list */
        PR_Lock(cache->hitLock);
        PR_REMOVE_AND_INIT_LINK(&nep->hit_list);
        PR_Unlock(cache->hitLock);
        PR_ASSERT(PR_LIST_HEAD(&nep->hit_list) == PR_LIST_TAIL(&nep->hit_list));

        /* Mark it for delete */
        nep->fDelete = 1;

        /* Increment total count of entries deleted */
        if (delCntIt == PR_TRUE) { 
            PR_AtomicIncrement((PRInt32 *)&cache->delCnt);
            PR_AtomicIncrement((PRInt32 *)&cache->busydCnt);
            if (outdCntIt == PR_TRUE)
                PR_AtomicIncrement((PRInt32 *)&cache->outdCnt);
        }
    }

    if (nep->refcnt == 0) {
        /*
         * Given that the entry's use count is zero, the caller had better have
         * the bucket lock (because he clearly doesn't have a refcnt)
         */
        PR_ASSERT(hasBucketLock == PR_TRUE);

        _NSFC_DestroyEntry(cache, nep, delCntIt);
    }

    /* Release the bucket lock if we weren't holding it on entry */
    if (hasBucketLock == PR_FALSE) {
        NSFC_RELEASEBUCKET(cache, bucket);
    }

    /* Cache contents have been modified */
    cache->sig++;

    return rfc;
}