filehash/ffdb_pagepool.c
static int
_ffdb_pagepool_reuse_bkt (ffdb_pagepool_t* pgp, ffdb_bkt_t** retbp)
{
  struct _ffdb_hqh *head;
  int ret = 0;
  int needwrite = 0;
  int reusepage = 0;
  ffdb_bkt_t* bp = 0;

  *retbp = 0;
  /**
   * Sanity check: LRU queues should not be empty
   */
  if (FFDB_CIRCLEQ_EMPTY(&pgp->lqh)) {
    fprintf (stderr, "_ffdb_pagepool_bkt: LRU queue is empty. Quit!\n");
    abort ();
  }

  /**
   * Walk the LRU queue now
   */
  FFDB_CIRCLEQ_FOREACH(bp, &pgp->lqh, lq) {

    reusepage = 0;
      
    if (!(FFDB_FLAG_ISSET(bp->flags, FFDB_PAGE_LOCKED)) && 
	!(FFDB_FLAG_ISSET(bp->flags, FFDB_PAGE_PINNED)) &&
	bp->waiters == 0) {
      /* This page is not locked and pinned, so it can be reused */
      /* And no one is waiting for it */
      reusepage = 1;
      /**
       * Flush if is dirty. 
       * This may not be efficient
       */
      if (FFDB_FLAG_ISSET(bp->flags, FFDB_PAGE_DIRTY)) {
	if (_ffdb_pagepool_write(pgp, bp) == -1) {
	  fprintf (stderr, "_ffdb_pagepool_bkt: page %d flush error\n",
		   bp->pgno);
	  ret = errno;
	  reusepage = 0;
	}
	else
	  needwrite = 1;
      }
      
      /**
       * If reusepage flag is set, this page can be reused
       */
      if (reusepage) {
#ifdef _FFDB_STATISTICS
	++pgp->pageswap;
#endif
	/* Remove from the hash and lru queues. */
	head = &pgp->hqh[FFDB_HASHKEY(bp->pgno)];
	FFDB_CIRCLEQ_REMOVE(head, bp, hq);
	FFDB_CIRCLEQ_REMOVE(&pgp->lqh, bp, lq);
#if 0
	fprintf (stderr, "Reuse remove page number %d\n", bp->pgno);
#endif

	bp->ref = 0;
	bp->waiters = 0;
	bp->flags = 0;
	bp->owner = FFDB_THREAD_ID;

	/* Now I need to set flags before unlock */
	bp->flags = FFDB_PAGE_PINNED | FFDB_PAGE_VALID;

#ifdef _FFDB_STATISTICS
	++pgp->pagereuse;
#endif
	*retbp = bp;
      }
    }
    if (reusepage)
      break;
  }
  /* not found any reuseable page */
  if ((*retbp) == 0)
    ret = -1;

  /* Now flush out some fraction of pages to speed up performance */
  if (needwrite) {
#ifdef _FFDB_DEBUG
    fprintf (stderr, "Flush %d pages out\n", pgp->maxcache/FFDB_WRITE_FRAC);
#endif
    _ffdb_pagepool_sync_i (pgp, pgp->maxcache/FFDB_WRITE_FRAC);
  }

  return ret;
}
/**
 * Get a page from cache when the page is not used by a thread
 * @param pgp pagepool pointer
 * @param bkt a new pointer to a bucket
 * @return 0 on success, -1 return no bucket can be reused. otherwise
 * error on flushing the unused page
 * Upon returning of this routine, the reused bucket's pinned flag is set
 *
 * This routine is called when pgp->lock is held
 */
Get a page from cache when the page is not used by a thread
@param pgp pagepool pointer
@param bkt a new pointer to a bucket
@return 0 on success, -1 return no bucket can be reused. otherwise
error on flushing the unused page
Upon returning of this routine, the reused bucket's pinned flag is set

This routine is called when pgp->lock is held
Get a page from cache when the page is not used by a thread @param pgp pagepool pointer @param bkt a new pointer to a bucket @return 0 on success - 1 return no bucket can be reused . otherwise error on flushing the unused page Upon returning of this routine the reused bucket ' s pinned flag is set This routine is called when pgp - > lock is held
static int
_ffdb_pagepool_reuse_bkt (ffdb_pagepool_t* pgp, ffdb_bkt_t** retbp)
{
  struct _ffdb_hqh *head;
  int ret = 0;
  int needwrite = 0;
  int reusepage = 0;
  ffdb_bkt_t* bp = 0;
  *retbp = 0;
  if (FFDB_CIRCLEQ_EMPTY(&pgp->lqh)) {
    fprintf (stderr, "_ffdb_pagepool_bkt: LRU queue is empty. Quit!\n");
    abort ();
  }
  FFDB_CIRCLEQ_FOREACH(bp, &pgp->lqh, lq) {
    reusepage = 0;
    if (!(FFDB_FLAG_ISSET(bp->flags, FFDB_PAGE_LOCKED)) && 
	!(FFDB_FLAG_ISSET(bp->flags, FFDB_PAGE_PINNED)) &&
	bp->waiters == 0) {
      reusepage = 1;
      if (FFDB_FLAG_ISSET(bp->flags, FFDB_PAGE_DIRTY)) {
	if (_ffdb_pagepool_write(pgp, bp) == -1) {
	  fprintf (stderr, "_ffdb_pagepool_bkt: page %d flush error\n",
		   bp->pgno);
	  ret = errno;
	  reusepage = 0;
	}
	else
	  needwrite = 1;
      }
      if (reusepage) {
#ifdef _FFDB_STATISTICS
	++pgp->pageswap;
#endif
	head = &pgp->hqh[FFDB_HASHKEY(bp->pgno)];
	FFDB_CIRCLEQ_REMOVE(head, bp, hq);
	FFDB_CIRCLEQ_REMOVE(&pgp->lqh, bp, lq);
#if 0
	fprintf (stderr, "Reuse remove page number %d\n", bp->pgno);
#endif
	bp->ref = 0;
	bp->waiters = 0;
	bp->flags = 0;
	bp->owner = FFDB_THREAD_ID;
	bp->flags = FFDB_PAGE_PINNED | FFDB_PAGE_VALID;
#ifdef _FFDB_STATISTICS
	++pgp->pagereuse;
#endif
	*retbp = bp;
      }
    }
    if (reusepage)
      break;
  }
  if ((*retbp) == 0)
    ret = -1;
  if (needwrite) {
#ifdef _FFDB_DEBUG
    fprintf (stderr, "Flush %d pages out\n", pgp->maxcache/FFDB_WRITE_FRAC);
#endif
    _ffdb_pagepool_sync_i (pgp, pgp->maxcache/FFDB_WRITE_FRAC);
  }
  return ret;
}
static int _ffdb_pagepool_reuse_bkt ( ffdb_pagepool_t * pgp , ffdb_bkt_t * * retbp ) { struct _ffdb_hqh * head ; int ret = 0 ; int needwrite = 0 ; int reusepage = 0 ; ffdb_bkt_t * bp = 0 ; * retbp = 0 ; if ( FFDB_CIRCLEQ_EMPTY ( & pgp -> lqh ) ) { fprintf ( stderr , " \n " ) ; abort ( ) ; } FFDB_CIRCLEQ_FOREACH ( bp , & pgp -> lqh , lq ) { reusepage = 0 ; if ( ! ( FFDB_FLAG_ISSET ( bp -> flags , FFDB_PAGE_LOCKED ) ) && ! ( FFDB_FLAG_ISSET ( bp -> flags , FFDB_PAGE_PINNED ) ) && bp -> waiters == 0 ) { reusepage = 1 ; if ( FFDB_FLAG_ISSET ( bp -> flags , FFDB_PAGE_DIRTY ) ) { if ( _ffdb_pagepool_write ( pgp , bp ) == -1 ) { fprintf ( stderr , " \n " , bp -> pgno ) ; ret = errno ; reusepage = 0 ; } else needwrite = 1 ; } if ( reusepage ) { #ifdef _FFDB_STATISTICS ++ pgp -> pageswap ; #endif head = & pgp -> hqh [ FFDB_HASHKEY ( bp -> pgno ) ] ; FFDB_CIRCLEQ_REMOVE ( head , bp , hq ) ; FFDB_CIRCLEQ_REMOVE ( & pgp -> lqh , bp , lq ) ; #if 0 fprintf ( stderr , " \n " , bp -> pgno ) ; #endif bp -> ref = 0 ; bp -> waiters = 0 ; bp -> flags = 0 ; bp -> owner = FFDB_THREAD_ID ; bp -> flags = FFDB_PAGE_PINNED | FFDB_PAGE_VALID ; #ifdef _FFDB_STATISTICS ++ pgp -> pagereuse ; #endif * retbp = bp ; } } if ( reusepage ) break ; } if ( ( * retbp ) == 0 ) ret = -1 ; if ( needwrite ) { #ifdef _FFDB_DEBUG fprintf ( stderr , " \n " , pgp -> maxcache / FFDB_WRITE_FRAC ) ; #endif _ffdb_pagepool_sync_i ( pgp , pgp -> maxcache / FFDB_WRITE_FRAC ) ; } return ret ; }
Get a page from cache when the page is not used by a thread
 @param pgp pagepool pointer
 @param bkt a new pointer to a bucket
 @return 0 on success, -1 return no bucket can be reused.
Get a page from cache when the page is not used by a thread @param pgp pagepool pointer @param bkt a new pointer to a bucket @return 0 on success - 1 return no bucket can be reused .
/**
   * Sanity check: LRU queues should not be empty
   */ /**
   * Walk the LRU queue now
   */ /* This page is not locked and pinned, so it can be reused */ /* And no one is waiting for it */ /**
       * Flush if is dirty. 
       * This may not be efficient
       */ /**
       * If reusepage flag is set, this page can be reused
       */ /* Remove from the hash and lru queues. */ /* Now I need to set flags before unlock */ /* not found any reuseable page */ /* Now flush out some fraction of pages to speed up performance */