filehash/ffdb_pagepool.c
int
ffdb_pagepool_change_page (ffdb_pagepool_t* pgp, void* mem, 
			   pgno_t newpagenum)
{
  struct _ffdb_hqh* head;
  ffdb_bkt_t* bp;
  unsigned int oldpagenum;

  FFDB_LOCK(pgp->lock);
#ifdef _FFDB_STATISTICS
  pgp->pagechange++;
#endif
  
  bp = (ffdb_bkt_t *)((char *)mem - sizeof (ffdb_bkt_t));

  if (!FFDB_FLAG_ISSET(bp->flags, FFDB_PAGE_PINNED)) {
    fprintf (stderr, "ffdb_pagepool_put_page: page %d is not pinned.\n",
	     bp->pgno);
#ifdef _FFDB_STATISTICS
    ffdb_pagepool_stat (pgp);
#endif
    abort();
  }

  /**
   * if there are waiters, we cannot change this page 
   * just do a regular put and come back later to change
   */
  if (bp->waiters > 0) {
    fprintf (stderr, "ffdb_pagepool_change: page %d has waiters\n",bp->pgno);
    FFDB_UNLOCK(pgp->lock);
    
    ffdb_pagepool_put_page (pgp, mem, 0);
    return EAGAIN;
  }

  /**
   * Here is a scary thing, if the flags has DIRTY bit set,
   * but bp->flags does not have the DIRTY bit set,
   * how do we control multiple threads simultaneous writes
   * suggestion: always set flag when you create pages
   */
  FFDB_FLAG_SET(bp->flags, FFDB_PAGE_DIRTY);

  /**
   * Derefence the page
   */
  bp->ref--;

  /* only thread holding this page can delete this page, and no other
   * threads waiting on this page 
   */
  head = &pgp->hqh[FFDB_HASHKEY(bp->pgno)];

  /* Remove from the hash and lru queues. */
  FFDB_CIRCLEQ_REMOVE(head, bp, hq);
  FFDB_CIRCLEQ_REMOVE(&pgp->lqh, bp, lq);

  /**
   * Remember old pagenumber
   */
  oldpagenum = bp->pgno;

  /**
   * Change page number
   */
  bp->pgno = newpagenum;

  /*
   * I am giving up the ownership
   */
  FFDB_THREAD_NULL(bp->owner);
  
  /** 
   * Now Unpin the page and wake up other threads waiting 
   */
  FFDB_FLAG_CLR(bp->flags, FFDB_PAGE_PINNED);

  /**
   * Now add this entry back to the lists
   */
  head = &pgp->hqh[FFDB_HASHKEY(bp->pgno)];
  FFDB_CIRCLEQ_INSERT_HEAD(head, bp, hq);
  FFDB_CIRCLEQ_INSERT_TAIL(&pgp->lqh, bp, lq);

  /**
   * Change number of pages if pages are moved back
   */
  if (newpagenum >= pgp->npages) {
    pgp->npages = newpagenum + 1;
#if 0
    fprintf (stderr, "reset number of pages = %d\n", pgp->npages);
#endif
  }

  /**
   * Clean out old disk content
   */
  _ffdb_clean_page_ondisk (pgp, oldpagenum);

  FFDB_UNLOCK(pgp->lock);
  return 0;
}
/**
 * Put a page back into the cache so that other threads can access this page
 * with new page number for this page
 *
 * 
 * @param pgp cache page pool pointer
 * @param mem user cached page memory will be returned
 * @param newpgnum a new pagenumber associated with this page
 * 
 * @return 0 if this page is successfully be put back into the cache. Otherwise
 * return -1 with an appropriate errno set
 */
Put a page back into the cache so that other threads can access this page
with new page number for this page

@param pgp cache page pool pointer
@param mem user cached page memory will be returned
@param newpgnum a new pagenumber associated with this page

@return 0 if this page is successfully be put back into the cache. Otherwise
return -1 with an appropriate errno set
Put a page back into the cache so that other threads can access this page with new page number for this page @param pgp cache page pool pointer @param mem user cached page memory will be returned @param newpgnum a new pagenumber associated with this page @return 0 if this page is successfully be put back into the cache . Otherwise return - 1 with an appropriate errno set
int
ffdb_pagepool_change_page (ffdb_pagepool_t* pgp, void* mem, 
			   pgno_t newpagenum)
{
  struct _ffdb_hqh* head;
  ffdb_bkt_t* bp;
  unsigned int oldpagenum;
  FFDB_LOCK(pgp->lock);
#ifdef _FFDB_STATISTICS
  pgp->pagechange++;
#endif
  bp = (ffdb_bkt_t *)((char *)mem - sizeof (ffdb_bkt_t));
  if (!FFDB_FLAG_ISSET(bp->flags, FFDB_PAGE_PINNED)) {
    fprintf (stderr, "ffdb_pagepool_put_page: page %d is not pinned.\n",
	     bp->pgno);
#ifdef _FFDB_STATISTICS
    ffdb_pagepool_stat (pgp);
#endif
    abort();
  }
  if (bp->waiters > 0) {
    fprintf (stderr, "ffdb_pagepool_change: page %d has waiters\n",bp->pgno);
    FFDB_UNLOCK(pgp->lock);
    ffdb_pagepool_put_page (pgp, mem, 0);
    return EAGAIN;
  }
  FFDB_FLAG_SET(bp->flags, FFDB_PAGE_DIRTY);
  bp->ref--;
  head = &pgp->hqh[FFDB_HASHKEY(bp->pgno)];
  FFDB_CIRCLEQ_REMOVE(head, bp, hq);
  FFDB_CIRCLEQ_REMOVE(&pgp->lqh, bp, lq);
  oldpagenum = bp->pgno;
  bp->pgno = newpagenum;
  FFDB_THREAD_NULL(bp->owner);
  FFDB_FLAG_CLR(bp->flags, FFDB_PAGE_PINNED);
  head = &pgp->hqh[FFDB_HASHKEY(bp->pgno)];
  FFDB_CIRCLEQ_INSERT_HEAD(head, bp, hq);
  FFDB_CIRCLEQ_INSERT_TAIL(&pgp->lqh, bp, lq);
  if (newpagenum >= pgp->npages) {
    pgp->npages = newpagenum + 1;
#if 0
    fprintf (stderr, "reset number of pages = %d\n", pgp->npages);
#endif
  }
  _ffdb_clean_page_ondisk (pgp, oldpagenum);
  FFDB_UNLOCK(pgp->lock);
  return 0;
}
int ffdb_pagepool_change_page ( ffdb_pagepool_t * pgp , void * mem , pgno_t newpagenum ) { struct _ffdb_hqh * head ; ffdb_bkt_t * bp ; unsigned int oldpagenum ; FFDB_LOCK ( pgp -> lock ) ; #ifdef _FFDB_STATISTICS pgp -> pagechange ++ ; #endif bp = ( ffdb_bkt_t * ) ( ( char * ) mem - sizeof ( ffdb_bkt_t ) ) ; if ( ! FFDB_FLAG_ISSET ( bp -> flags , FFDB_PAGE_PINNED ) ) { fprintf ( stderr , " \n " , bp -> pgno ) ; #ifdef _FFDB_STATISTICS ffdb_pagepool_stat ( pgp ) ; #endif abort ( ) ; } if ( bp -> waiters > 0 ) { fprintf ( stderr , " \n " , bp -> pgno ) ; FFDB_UNLOCK ( pgp -> lock ) ; ffdb_pagepool_put_page ( pgp , mem , 0 ) ; return EAGAIN ; } FFDB_FLAG_SET ( bp -> flags , FFDB_PAGE_DIRTY ) ; bp -> ref -- ; head = & pgp -> hqh [ FFDB_HASHKEY ( bp -> pgno ) ] ; FFDB_CIRCLEQ_REMOVE ( head , bp , hq ) ; FFDB_CIRCLEQ_REMOVE ( & pgp -> lqh , bp , lq ) ; oldpagenum = bp -> pgno ; bp -> pgno = newpagenum ; FFDB_THREAD_NULL ( bp -> owner ) ; FFDB_FLAG_CLR ( bp -> flags , FFDB_PAGE_PINNED ) ; head = & pgp -> hqh [ FFDB_HASHKEY ( bp -> pgno ) ] ; FFDB_CIRCLEQ_INSERT_HEAD ( head , bp , hq ) ; FFDB_CIRCLEQ_INSERT_TAIL ( & pgp -> lqh , bp , lq ) ; if ( newpagenum >= pgp -> npages ) { pgp -> npages = newpagenum + 1 ; #if 0 fprintf ( stderr , " \n " , pgp -> npages ) ; #endif } _ffdb_clean_page_ondisk ( pgp , oldpagenum ) ; FFDB_UNLOCK ( pgp -> lock ) ; return 0 ; }
Put a page back into the cache so that other threads can access this page
 with new page number for this page
Put a page back into the cache so that other threads can access this page with new page number for this page
/**
   * if there are waiters, we cannot change this page 
   * just do a regular put and come back later to change
   */ /**
   * Here is a scary thing, if the flags has DIRTY bit set,
   * but bp->flags does not have the DIRTY bit set,
   * how do we control multiple threads simultaneous writes
   * suggestion: always set flag when you create pages
   */ /**
   * Derefence the page
   */ /* only thread holding this page can delete this page, and no other
   * threads waiting on this page 
   */ /* Remove from the hash and lru queues. */ /**
   * Remember old pagenumber
   */ /**
   * Change page number
   */ /*
   * I am giving up the ownership
   */ /** 
   * Now Unpin the page and wake up other threads waiting 
   */ /**
   * Now add this entry back to the lists
   */ /**
   * Change number of pages if pages are moved back
   */ /**
   * Clean out old disk content
   */