Beispiel #1
0
void *
mutt_hcache_fetch_raw (header_cache_t *h, const char *filename,
                       size_t(*keylen) (const char *fn))
{
#ifndef HAVE_DB4
  char path[_POSIX_PATH_MAX];
  int ksize;
#endif
#ifdef HAVE_QDBM
  char *data = NULL;
#elif HAVE_TC
  void *data;
  int sp;
#elif HAVE_GDBM
  datum key;
  datum data;
#elif HAVE_DB4
  DBT key;
  DBT data;
#endif
  
  if (!h)
    return NULL;
  
#ifdef HAVE_DB4
  if (filename[0] == '/')
    filename++;

  mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename));
  mutt_hcache_dbt_empty_init(&data);
  data.flags = DB_DBT_MALLOC;
  
  h->db->get(h->db, NULL, &key, &data, 0);
  
  return data.data;
#else
  strncpy(path, h->folder, sizeof (path));
  safe_strcat(path, sizeof (path), filename);

  ksize = strlen (h->folder) + keylen (path + strlen (h->folder));  
#endif
#ifdef HAVE_QDBM
  data = vlget(h->db, path, ksize, NULL);
  
  return data;
#elif HAVE_TC
  data = tcbdbget(h->db, path, ksize, &sp);

  return data;
#elif HAVE_GDBM
  key.dptr = path;
  key.dsize = ksize;
  
  data = gdbm_fetch(h->db, key);
  
  return data.dptr;
#endif
}
Beispiel #2
0
int
mutt_hcache_store_raw (header_cache_t* h, const char* filename, void* data,
                       size_t dlen, size_t(*keylen) (const char* fn))
{
#ifndef HAVE_DB4
  char path[_POSIX_PATH_MAX];
  int ksize;
#endif
#if HAVE_GDBM
  datum key;
  datum databuf;
#elif HAVE_DB4
  DBT key;
  DBT databuf;
#endif
  
  if (!h)
    return -1;

#if HAVE_DB4
  if (filename[0] == '/')
    filename++;
  
  mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename));
  
  mutt_hcache_dbt_empty_init(&databuf);
  databuf.flags = DB_DBT_USERMEM;
  databuf.data = data;
  databuf.size = dlen;
  databuf.ulen = dlen;
  
  return h->db->put(h->db, NULL, &key, &databuf, 0);
#else
  strncpy(path, h->folder, sizeof (path));
  safe_strcat(path, sizeof (path), filename);

  ksize = strlen(h->folder) + keylen(path + strlen(h->folder));
#endif
#if HAVE_QDBM
  return vlput(h->db, path, ksize, data, dlen, VL_DOVER);
#elif HAVE_TC
  return tcbdbput(h->db, path, ksize, data, dlen);
#elif HAVE_GDBM
  key.dptr = path;
  key.dsize = ksize;
  
  databuf.dsize = dlen;
  databuf.dptr = data;
  
  return gdbm_store(h->db, key, databuf, GDBM_REPLACE);
#endif
}
bool LookupIter::hasNext() {

    int next_pos = position + 1;
    if (next_pos >= node->numkeys) {
        /* Reached end of node */
        return false;
    }
    if (strncmp(&(node->data[next_pos*keylen(&keyType)]), key, keylen(&keyType)) != 0) {
        /* The key at next position doesn't match the iterator's key*/
        return false;
    }
    return true;
}
Beispiel #4
0
int TreeNode::addData(KeyType keytype,char *key, int payloadlen,char *payload,int position){
	int numPointers = this->numkeys;
	for(int j = numkeys-1; j >= (position); j--) {
		strncpy(&(data[(j+1)*keylen(&keytype)]), &(data[j*keylen(&keytype)]),keylen(&keytype));
	}
	strncpy(&(data[(position)*keylen(&keytype)]),key, keylen(&keytype));
	if (this->flag!= 'c') {
		position += 1;
		numPointers ++;
	}
	for(int j = (DATA_SIZE-numPointers*payloadlen); j < (DATA_SIZE-position*payloadlen); j+=payloadlen) {
			strncpy(&(data[j-payloadlen]), &(data[j]),payloadlen);
	}
	strncpy(&(data[DATA_SIZE-(position+1)*payloadlen]),payload,payloadlen);
	return 0;
}
Beispiel #5
0
int
mutt_hcache_delete(header_cache_t *h, const char *filename,
		   size_t(*keylen) (const char *fn))
{
  DBT key;

  if (!h)
    return -1;

  if (filename[0] == '/')
    filename++;

  mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename));
  return h->db->del(h->db, NULL, &key, 0);
}
Beispiel #6
0
int
mutt_hcache_delete(header_cache_t *h, const char *filename,
		   size_t(*keylen) (const char *fn))
{
  char path[_POSIX_PATH_MAX];
  int ksize;

  if (!h)
    return -1;

  strncpy(path, h->folder, sizeof (path));
  safe_strcat(path, sizeof (path), filename);

  ksize = strlen(h->folder) + keylen(path + strlen(h->folder));

  return tcbdbout(h->db, path, ksize);
}
Beispiel #7
0
DbStatus btree1NextKey (DbCursor *dbCursor, DbMap *map) {
Btree1Cursor *cursor = (Btree1Cursor *)((char *)dbCursor + dbCursor->xtra);
uint8_t *key;

	switch (dbCursor->state) {
	  case CursorNone:
		btree1LeftKey(dbCursor, map);
		break;

	  case CursorRightEof:
		return DB_CURSOR_eof;

	  default:
		break;
	}

	while (true) {
	  uint32_t max = cursor->page->cnt;

	  if (!cursor->page->right.bits)
		max--;

	  while (++cursor->slotIdx <= max) {
		Btree1Slot *slot = slotptr(cursor->page, cursor->slotIdx);

		if (slot->dead)
		  continue;

		key = keyaddr(cursor->page, slot->off);
		dbCursor->key = key + keypre(key);
		dbCursor->keyLen = keylen(key);
		dbCursor->state = CursorPosAt;
		return DB_OK;
	  }

	  if (cursor->page->right.bits)
		cursor->page = getObj(map, cursor->page->right);
	  else
		break;

	  cursor->slotIdx = 0;
	}

	dbCursor->state = CursorRightEof;
	return DB_CURSOR_eof;
}
Beispiel #8
0
int btree1KeyCmp (uint8_t *key1, uint8_t *key2, uint32_t len2)
{
uint32_t len1 = keylen(key1);
int ans;

	key1 += keypre(key1);

	if((ans = memcmp (key1, key2, len1 > len2 ? len2 : len1)))
		return ans;

	if( len1 > len2 )
		return 1;
	if( len1 < len2 )
		return -1;

	return 0;
}
Beispiel #9
0
int
mutt_hcache_delete(header_cache_t *h, const char *filename,
		   size_t(*keylen) (const char *fn))
{
  datum key;
  char path[_POSIX_PATH_MAX];

  if (!h)
    return -1;

  strncpy(path, h->folder, sizeof (path));
  safe_strcat(path, sizeof (path), filename);

  key.dptr = path;
  key.dsize = strlen(h->folder) + keylen(path + strlen(h->folder));

  return gdbm_delete(h->db, key);
}
Beispiel #10
0
DbStatus btree1PrevKey (DbCursor *dbCursor, DbMap *map) {
Btree1Cursor *cursor = (Btree1Cursor *)((char *)dbCursor + dbCursor->xtra);
uint8_t *key;

	switch (dbCursor->state) {
	  case CursorNone:
		btree1RightKey(dbCursor, map);
		break;

	  case CursorLeftEof:
		return DB_CURSOR_eof;

	  default:
		break;
	}

	while (true) {
	  if (cursor->slotIdx > 1) {
		Btree1Slot *slot = slotptr(cursor->page, --cursor->slotIdx);

		if (slot->dead)
		  continue;

		key = keyaddr(cursor->page, slot->off);
		dbCursor->key = key + keypre(key);
		dbCursor->keyLen = keylen(key);
		dbCursor->state = CursorPosAt;
		return DB_OK;
	  }

	  if (cursor->page->left.bits)
		cursor->page = getObj(map, cursor->page->left);
	  else
		break;

	  cursor->slotIdx = cursor->page->cnt + 1;
	}

	dbCursor->state = CursorLeftEof;
	return DB_CURSOR_eof;
}
Beispiel #11
0
bool LookupIter::hasNext() {
    /*
     * TODO: Fill in code
     *
     * Hint: See usage in Index.cpp.main() to understand functionality
     * Also see LookupIter.h
     */
     if(isNull()) return false;
     int size = node->numkeys;
     if(position<=size-2){
		 char tempNodekey[keylen(&keyType)];
		 node->getKey(keyType,tempNodekey,position+1);
		 if(compare(key,tempNodekey,keyType)==0){
			 return true;
			 }
		 else return false;
		 }
	 else{
		 return false;
		 }
}
Beispiel #12
0
int TreeNode::getKey(KeyType keytype,char *key,int position){
	int keystart = 0;
	utils->copyBytes(key,&(data[keystart+(position*keylen(&keytype))]),keylen(&keytype));
	return 0;
}
Beispiel #13
0
DbStatus btree1LoadPage(DbMap *map, Btree1Set *set, void *key, uint32_t keyLen, uint8_t lvl, Btree1Lock lock, bool stopper) {
Btree1Index *btree1 = btree1index(map);
uint8_t drill = 0xff, *ptr;
Btree1Page *prevPage = NULL;
Btree1Lock mode, prevMode;
DbAddr prevPageNo;

  set->pageNo.bits = btree1->root.bits;
  prevPageNo.bits = 0;

  //  start at our idea of the root level of the btree1 and drill down

  do {
	// determine lock mode of drill level

	mode = (drill == lvl) ? lock : Btree1_lockRead; 
	set->page = getObj(map, set->pageNo);

	//	release parent or left sibling page

	if( prevPageNo.bits ) {
	  btree1UnlockPage(prevPage, prevMode);
	  prevPageNo.bits = 0;
	}

 	// obtain mode lock

	btree1LockPage(set->page, mode);

	if( set->page->free )
		return DB_BTREE_error;

	// re-read and re-lock root after determining actual level of root

	if( set->page->lvl != drill) {
		assert(drill == 0xff);
		drill = set->page->lvl;

		if( lock != Btree1_lockRead && drill == lvl ) {
		  btree1UnlockPage(set->page, mode);
		  continue;
		}
	}

	assert(lvl <= set->page->lvl);

	prevPageNo.bits = set->pageNo.bits;
	prevPage = set->page;
	prevMode = mode;

	//  find key on page at this level
	//  and descend to requested level

	if( !set->page->kill )
	 if( (set->slotIdx = btree1FindSlot (set->page, key, keyLen, stopper)) ) {
	  if( drill == lvl )
		return DB_OK;

	  // find next non-dead slot -- the fence key if nothing else

	  while( slotptr(set->page, set->slotIdx)->dead )
		if( set->slotIdx++ < set->page->cnt )
		  continue;
		else
		  return DB_BTREE_error;

	  // get next page down

	  ptr = keyptr(set->page, set->slotIdx);
	  set->pageNo.bits = btree1GetPageNo(ptr + keypre(ptr), keylen(ptr));

	  assert(drill > 0);
	  drill--;
	  continue;
	 }

	//  or slide right into next page

	set->pageNo.bits = set->page->right.bits;
  } while( set->pageNo.bits );

  // return error on end of right chain

  return DB_BTREE_error;
}
Beispiel #14
0
DbStatus btree1CleanPage(Handle *index, Btree1Set *set, uint32_t totKeyLen) {
Btree1Index *btree1 = btree1index(index->map);
Btree1Slot librarian, *source, *dest;
uint32_t size = btree1->pageSize;
Btree1Page *page = set->page;
uint32_t max = page->cnt;
uint32_t len, cnt, idx;
uint32_t newSlot = max;
Btree1PageType type;
Btree1Page *frame;
uint8_t *key;
DbAddr addr;

	librarian.bits = 0;
	librarian.type = Btree1_librarian;
	librarian.dead = 1;

	if( !page->lvl ) {
		size <<= btree1->leafXtra;
		type = Btree1_leafPage;
	} else {
		type = Btree1_interior;
	}

	if( page->min >= (max+1) * sizeof(Btree1Slot) + sizeof(*page) + totKeyLen )
		return DB_OK;

	//	skip cleanup and proceed directly to split
	//	if there's not enough garbage
	//	to bother with.

	if( page->garbage < size / 5 )
		return DB_BTREE_needssplit;

	if( (addr.bits = allocObj(index->map, listFree(index, type), NULL, type, size, false)) )
		frame = getObj(index->map, addr);
	else
		return DB_ERROR_outofmemory;

	memcpy (frame, page, size);

	// skip page info and set rest of page to zero

	memset (page+1, 0, size - sizeof(*page));
	page->garbage = 0;
	page->act = 0;

	cnt = 0;
	idx = 0;

	source = slotptr(frame, cnt);
	dest = slotptr(page, idx);

	// clean up page first by
	// removing deleted keys

	while( source++, cnt++ < max ) {
		if( cnt == set->slotIdx )
			newSlot = idx + 2;

		if( source->dead )
			continue;

		// copy the active key across

		key = keyaddr(frame, source->off);
		len = keylen(key) + keypre(key);
		size -= len;

		memcpy ((uint8_t *)page + size, key, len);

		// make a librarian slot

		if (cnt < max) {
			(++dest)->bits = librarian.bits;
			++idx;
		}

		// set up the slot

		(++dest)->bits = source->bits;
		dest->off = size;
		idx++;

		page->act++;
	}

	page->min = size;
	page->cnt = idx;

	//	update insert slot index
	//	for newly cleaned-up page

	set->slotIdx = newSlot;

	//  return temporary frame

	addSlotToFrame(index->map, listFree(index,addr.type), NULL, addr.bits);

	//	see if page has enough space now, or does it still need splitting?

	if( page->min >= (idx+1) * sizeof(Btree1Slot) + sizeof(*page) + totKeyLen )
		return DB_OK;

	return DB_BTREE_needssplit;
}
Beispiel #15
0
DbStatus btree1SplitRoot(Handle *index, Btree1Set *root, DbAddr right, uint8_t *leftKey) {
Btree1Index *btree1 = btree1index(index->map);
uint32_t keyLen, nxt = btree1->pageSize;
Btree1Page *leftPage, *rightPage;
Btree1Slot *slot;
uint8_t *ptr;
uint32_t off;
DbAddr left;

	//  Obtain an empty page to use, and copy the current
	//  root contents into it, e.g. lower keys

	if( (left.bits = btree1NewPage(index, root->page->lvl)) )
		leftPage = getObj(index->map, left);
	else
		return DB_ERROR_outofmemory;

	//	copy in new smaller keys into left page
	//	(clear the latches)

	memcpy (leftPage->latch + 1, root->page->latch + 1, btree1->pageSize - sizeof(*leftPage->latch));
	rightPage = getObj(index->map, right);
	rightPage->left.bits = left.bits;

	// preserve the page info at the bottom
	// of higher keys and set rest to zero

	memset(root->page+1, 0, btree1->pageSize - sizeof(*root->page));

	// insert stopper key on root page
	// pointing to right half page 
	// and increase the root height

	nxt -= 1 + sizeof(uint64_t);
	slot = slotptr(root->page, 2);
	slot->type = Btree1_stopper;
	slot->off = nxt;

	ptr = keyaddr(root->page, nxt);
	btree1PutPageNo(ptr + 1, 0, right.bits);
	ptr[0] = sizeof(uint64_t);

	// next insert lower keys (left) fence key on newroot page as
	// first key and reserve space for the key.

	keyLen = keylen(leftKey);
	off = keypre(leftKey);

	nxt -= keyLen + off;
	slot = slotptr(root->page, 1);
	slot->type = Btree1_indexed;
	slot->off = nxt;

	//	construct lower (left) page key

	ptr = keyaddr(root->page, nxt);
	memcpy (ptr + off, leftKey + keypre(leftKey), keyLen - sizeof(uint64_t));
	btree1PutPageNo(ptr + off, keyLen - sizeof(uint64_t), left.bits);

	if (off == 1)
		ptr[0] = keyLen;
	else
		ptr[0] = keyLen / 256 | 0x80, ptr[1] = keyLen;
	
	root->page->right.bits = 0;
	root->page->min = nxt;
	root->page->cnt = 2;
	root->page->act = 2;
	root->page->lvl++;

	// release root page

	btree1UnlockPage(root->page, Btree1_lockWrite);
	return DB_OK;
}
Beispiel #16
0
DbStatus btree1SplitPage (Handle *index, Btree1Set *set) {
uint8_t leftKey[Btree1_maxkey], rightKey[Btree1_maxkey];
Btree1Index *btree1 = btree1index(index->map);
uint32_t cnt = 0, idx = 0, max, nxt, off;
Btree1Slot librarian, *source, *dest;
uint32_t size = btree1->pageSize;
Btree1Page *frame, *rightPage;
uint8_t lvl = set->page->lvl;
uint32_t totLen, keyLen;
uint8_t *key = NULL;
DbAddr right, addr;
bool stopper;
DbStatus stat;

#ifdef DEBUG
	atomicAdd32(&Splits, 1);
#endif

	librarian.bits = 0;
	librarian.type = Btree1_librarian;
	librarian.dead = 1;

	if( !set->page->lvl )
		size <<= btree1->leafXtra;

	//	get new page and write higher keys to it.

	if( (right.bits = btree1NewPage(index, lvl)) )
		rightPage = getObj(index->map, right);
	else
		return DB_ERROR_outofmemory;

	max = set->page->cnt;
	cnt = max / 2;
	nxt = size;
	idx = 0;

	source = slotptr(set->page, cnt);
	dest = slotptr(rightPage, 0);

	while( source++, cnt++ < max ) {
		if( source->dead )
			continue;

		key = keyaddr(set->page, source->off);
		totLen = keylen(key) + keypre(key);
		nxt -= totLen;

		memcpy (keyaddr(rightPage, nxt), key, totLen);
		rightPage->act++;

		//	add librarian slot

		if (cnt < max) {
			(++dest)->bits = librarian.bits;
			dest->off = nxt;
			idx++;
		}

		//  add actual slot

		(++dest)->bits = source->bits;
		dest->off = nxt;
		idx++;
	}

	//	remember right fence key for larger page
	//	extend right leaf fence key with
	//	the right page number on leaf page.

	stopper = dest->type == Btree1_stopper;
	keyLen = keylen(key);

	if( set->page->lvl)
		keyLen -= sizeof(uint64_t);		// strip off pageNo

	if( keyLen + sizeof(uint64_t) < 128 )
		off = 1;
	else
		off = 2;

	//	copy key and add pageNo

	memcpy (rightKey + off, key + keypre(key), keyLen);
	btree1PutPageNo(rightKey + off, keyLen, right.bits);
	keyLen += sizeof(uint64_t);

	if (off == 1)
		rightKey[0] = keyLen;
	else
		rightKey[0] = keyLen / 256 | 0x80, rightKey[1] = keyLen;

	rightPage->min = nxt;
	rightPage->cnt = idx;
	rightPage->lvl = lvl;

	// link right node

	if( set->pageNo.type != Btree1_rootPage ) {
		rightPage->right.bits = set->page->right.bits;
		rightPage->left.bits = set->pageNo.bits;

		if( !lvl && rightPage->right.bits ) {
			Btree1Page *farRight = getObj(index->map, rightPage->right);
			btree1LockPage (farRight, Btree1_lockLink);
			farRight->left.bits = right.bits;
			btree1UnlockPage (farRight, Btree1_lockLink);
		}
	}

	//	copy lower keys from temporary frame back into old page

	if( (addr.bits = btree1NewPage(index, lvl)) )
		frame = getObj(index->map, addr);
	else
		return DB_ERROR_outofmemory;

	memcpy (frame, set->page, size);
	memset (set->page+1, 0, size - sizeof(*set->page));

	set->page->garbage = 0;
	set->page->act = 0;
	nxt = size;
	max /= 2;
	cnt = 0;
	idx = 0;

	//  ignore librarian max key

	if( slotptr(frame, max)->type == Btree1_librarian )
		max--;

	source = slotptr(frame, 0);
	dest = slotptr(set->page, 0);

#ifdef DEBUG
	key = keyaddr(frame, source[2].off);
	assert(keylen(key) > 0);
#endif
	//  assemble page of smaller keys from temporary frame copy

	while( source++, cnt++ < max ) {
		if( source->dead )
			continue;

		key = keyaddr(frame, source->off);
		totLen = keylen(key) + keypre(key);
		nxt -= totLen;

		memcpy (keyaddr(set->page, nxt), key, totLen);

		//	add librarian slot, except before fence key

		if (cnt < max) {
			(++dest)->bits = librarian.bits;
			dest->off = nxt;
			idx++;
		}

		//	add actual slot

		(++dest)->bits = source->bits;
		dest->off = nxt;
		idx++;

		set->page->act++;
	}

	set->page->right.bits = right.bits;
	set->page->min = nxt;
	set->page->cnt = idx;

	//	remember left fence key for smaller page
	//	extend left leaf fence key with
	//	the left page number.

	keyLen = keylen(key);

	if( set->page->lvl)
		keyLen -= sizeof(uint64_t);		// strip off pageNo

	if( keyLen + sizeof(uint64_t) < 128 )
		off = 1;
	else
		off = 2;

	//	copy key and add pageNo

	memcpy (leftKey + off, key + keypre(key), keyLen);
	btree1PutPageNo(leftKey + off, keyLen, set->pageNo.bits);
	keyLen += sizeof(uint64_t);

	if (off == 1)
		leftKey[0] = keyLen;
	else
		leftKey[0] = keyLen / 256 | 0x80, leftKey[1] = keyLen;

	//  return temporary frame

	addSlotToFrame(index->map, listFree(index, addr.type), NULL, addr.bits);

	// if current page is the root page, split it

	if( set->pageNo.type == Btree1_rootPage )
		return btree1SplitRoot (index, set, right, leftKey);

	// insert new fences in their parent pages

	btree1LockPage (rightPage, Btree1_lockParent);
	btree1LockPage (set->page, Btree1_lockParent);
	btree1UnlockPage (set->page, Btree1_lockWrite);

	// insert new fence for reformulated left block of smaller keys

	if( (stat = btree1InsertKey(index, leftKey + keypre(leftKey), keylen(leftKey), lvl+1, Btree1_indexed) ))
		return stat;

	// switch fence for right block of larger keys to new right page

	if( (stat = btree1FixKey(index, rightKey, lvl+1, stopper) ))
		return stat;

	btree1UnlockPage (set->page, Btree1_lockParent);
	btree1UnlockPage (rightPage, Btree1_lockParent);
	return DB_OK;
}