Exemple #1
0
static const StoreEntry *
heap_walkNext(RemovalPolicyWalker * walker)
{
    HeapWalkData *heap_walk = walker->_data;
    RemovalPolicy *policy = walker->_policy;
    HeapPolicyData *heap = policy->_data;
    StoreEntry *entry;
    if (heap_walk->current >= heap_nodes(heap->heap))
	return NULL;		/* done */
    entry = (StoreEntry *) heap_peep(heap->heap, heap_walk->current++);
    return entry;
}
Exemple #2
0
static StoreEntry *
heap_purgeNext(RemovalPurgeWalker * walker)
{
    HeapPurgeData *heap_walker = walker->_data;
    RemovalPolicy *policy = walker->_policy;
    HeapPolicyData *heap = policy->_data;
    StoreEntry *entry;
    heap_key age;
  try_again:
    if (!heap_nodes(heap->heap) > 0)
	return NULL;		/* done */
    age = heap_peepminkey(heap->heap);
    entry = heap_extractmin(heap->heap);
    if (storeEntryLocked(entry)) {
	storeLockObject(entry);
	linklistPush(&heap_walker->locked_entries, entry);
	goto try_again;
    }
    heap_walker->min_age = age;
    SET_POLICY_NODE(entry, NULL);
    return entry;
}
Exemple #3
0
/*
 * Compute the heap skew for HEAP, a measure of how out-of-order the
 * elements in the heap are.  The skew of a heap node is the difference
 * between its current position in the heap and where it would be if the
 * heap were in sorted order.  To compute this we have to sort the heap.  At
 * the end if the flag REPLACE is non-zero the heap will be returned in
 * sorted order (with skew == 0).  Note: using REPLACE does not help the
 * performance of the heap, so only do this if you really want to have a
 * sorted heap.  It is faster not to replace.
 */
float
calc_heap_skew(heap * heap, int replace)
{
    heap_node **nodes;
    long id, diff, skew = 0;
#ifdef	HEAP_DEBUG_SKEW
    long skewsq = 0;
#endif /* HEAP_DEBUG_SKEW */
    float norm = 0;
    unsigned long max;

    /* 
     * Lock the heap to copy it.  If replacing it need to keep the heap locked
     * until we are all done.
     */
    mutex_lock(hp->lock);

    max = heap_nodes(heap);

    /* 
     * Copy the heap nodes to a new storage area for offline sorting.
     */
    nodes = xmalloc(max * sizeof(heap_node *));
    memcpy(nodes, heap->nodes, max * sizeof(heap_node *));

    if (replace == 0) {
	/* 
	 * Unlock the heap to allow updates from other threads before the sort.
	 * This allows other heap operations to proceed concurrently with the
	 * heap skew computation on the heap at the time of the call ...
	 */
	mutex_unlock(hp->lock);
    }
    qsort(nodes, max, sizeof(heap_node *), compare_heap_keys);

    for (id = 0; id < max; id++) {
	diff = id - nodes[id]->id;
	skew += abs(diff);

#ifdef	HEAP_DEBUG_SKEW
	skewsq += diff * diff;
#ifdef	HEAP_DEBUG_ALL
	printf("%d\tKey = %f, diff = %d\n", id, nodes[id]->key, diff);
#endif /* HEAP_DEBUG */
#endif /* HEAP_DEBUG_SKEW */
    }

    if (replace != 0) {
	/* 
	 * Replace the original heap with the newly sorted heap and let it
	 * continue.  Then compute the skew using the copy of the previous heap
	 * which we maintain as private data.
	 */
	memcpy(heap->nodes, nodes, max * sizeof(heap_node *));

	for (id = 0; id < max; id++) {
	    /* 
	     * Fix up all the ID values in the copied nodes.
	     */
	    heap->nodes[id]->id = id;
	}

	mutex_unlock(hp->lock);
    }
    /* 
     * The skew value is normalized to a range of [0..1]; the distribution
     * appears to be a skewed Gaussian distribution.  For random insertions
     * into a heap the normalized skew will be slightly less than 0.5.  The
     * maximum value of skew/N^2 (for any value of N) is about 0.39 and is
     * fairly stable.
     */
    norm = skew * 2.56 / (max * max);

    /* 
     * Free the nodes array; note this is just an array of pointers, not data!
     */
    xfree(nodes);
    return norm;
}
Exemple #4
0
int
storeDirWriteCleanLogs(int reopen)
{
    StoreEntry *e = NULL;
    int n = 0;
    struct timeval start;
    double dt;
    SwapDir *sd;
    int dirn;
    int N = Config.cacheSwap.n_configured;
#if HEAP_REPLACEMENT
    int node;
#else
    dlink_node *m;
#endif
    if (store_dirs_rebuilding) {
	debug(20, 1) ("Not currently OK to rewrite swap log.\n");
	debug(20, 1) ("storeDirWriteCleanLogs: Operation aborted.\n");
	return 0;
    }
    debug(20, 1) ("storeDirWriteCleanLogs: Starting...\n");
    getCurrentTime();
    start = current_time;
    for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
	sd = &Config.cacheSwap.swapDirs[dirn];
	if (sd->log.clean.open(sd) < 0) {
	    debug(20, 1) ("log.clean.open() failed for dir #%d\n", sd->index);
	    continue;
	}
    }
#if HEAP_REPLACEMENT
    if (NULL == store_heap)
	return 0;
    for (node = 0; node < heap_nodes(store_heap); node++)
#else
    for (m = store_list.tail; m; m = m->prev)
#endif
    {
#if HEAP_REPLACEMENT
	e = (StoreEntry *) heap_peep(store_heap, node);
#else
	e = m->data;
#endif
	if (e->swap_file_number < 0)
	    continue;
	if (e->swap_status != SWAPOUT_DONE)
	    continue;
	if (e->swap_file_sz <= 0)
	    continue;
	if (EBIT_TEST(e->flags, RELEASE_REQUEST))
	    continue;
	if (EBIT_TEST(e->flags, KEY_PRIVATE))
	    continue;
	if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
	    continue;
	dirn = storeDirNumber(e->swap_file_number);
	sd = &Config.cacheSwap.swapDirs[dirn];
	if (NULL == sd->log.clean.write)
	    continue;
	sd->log.clean.write(e, sd);
	if ((++n & 0xFFFF) == 0) {
	    getCurrentTime();
	    debug(20, 1) ("  %7d entries written so far.\n", n);
	}
    }
    /* flush */
    for (dirn = 0; dirn < N; dirn++) {
	sd = &Config.cacheSwap.swapDirs[dirn];
	if (NULL == sd->log.clean.write)
	    continue;
	sd->log.clean.write(NULL, sd);
    }
    if (reopen)
	storeDirOpenSwapLogs();
    getCurrentTime();
    dt = tvSubDsec(start, current_time);
    debug(20, 1) ("  Finished.  Wrote %d entries.\n", n);
    debug(20, 1) ("  Took %3.1f seconds (%6.1f entries/sec).\n",
	dt, (double) n / (dt > 0.0 ? dt : 1.0));
    return n;
}