예제 #1
0
파일: recnum.c 프로젝트: tevren/ruby-bdb
static VALUE
bdb_intern_shift_pop(VALUE obj, int depart, int len)
{
    bdb_DB *dbst;
    DB_TXN *txnid;
    DBC *dbcp;
    DBT key, data;
    int i, ret, flags;
    db_recno_t recno;
    VALUE res;

    rb_secure(4);
    INIT_TXN(txnid, obj, dbst);
#if HAVE_DB_CURSOR_4
    bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0));
#else
    bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp));
#endif
    SET_PARTIAL(dbst, data);
    flags = TEST_INIT_LOCK(dbst);
    res = rb_ary_new2(len);
    for (i = 0; i < len; i++) {
	MEMZERO(&key, DBT, 1);
	INIT_RECNO(dbst, key, recno);
	MEMZERO(&data, DBT, 1);
	data.flags = DB_DBT_MALLOC;
	bdb_cache_error(dbcp->c_get(dbcp, &key, &data, depart | flags),
			dbcp->c_close(dbcp), ret);
	if (ret == DB_NOTFOUND) break;
	rb_ary_push(res, bdb_test_load(obj, &data, FILTER_VALUE));
	bdb_cache_error(dbcp->c_del(dbcp, 0), dbcp->c_close(dbcp), ret);
	if (dbst->len > 0) dbst->len--;
    }
    dbcp->c_close(dbcp);
    if (RARRAY_LEN(res) == 0) return Qnil;
    else if (RARRAY_LEN(res) == 1) return RARRAY_PTR(res)[0];
    else return res;
}
예제 #2
0
/**
 * e_book_backend_db_cache_get_contacts:
 * @db: DB Handle
 * @query: an s-expression
 *
 * Returns a list of #EContact elements from @cache matching @query.
 * When done with the list, the caller must unref the contacts and
 * free the list.
 *
 * Returns: A #GList of pointers to #EContact.
 **/
GList *
e_book_backend_db_cache_get_contacts (DB *db,
                                      const gchar *query)
{
	DBC	*dbc;
	DBT	uid_dbt, vcard_dbt;
	gint	db_error;
	GList *list = NULL;
	EBookBackendSExp *sexp = NULL;
	EContact *contact;

	if (query) {
		sexp = e_book_backend_sexp_new (query);
		if (!sexp)
			return NULL;
	}

	db_error = db->cursor (db, NULL, &dbc, 0);
	if (db_error != 0) {
		g_warning ("db->cursor failed with %d", db_error);
		if (sexp)
			g_object_unref (sexp);
		return NULL;
	}

	memset (&vcard_dbt, 0 , sizeof (vcard_dbt));
	memset (&uid_dbt, 0, sizeof (uid_dbt));
	db_error = dbc->c_get (dbc, &uid_dbt, &vcard_dbt, DB_FIRST);

	while (db_error == 0) {
		if (vcard_dbt.data && !strncmp (vcard_dbt.data, "BEGIN:VCARD", 11)) {
			contact = e_contact_new_from_vcard (vcard_dbt.data);

			if (!sexp || e_book_backend_sexp_match_contact (sexp, contact))
				list = g_list_prepend (list, contact);
			else
				g_object_unref (contact);
		}
		db_error = dbc->c_get (dbc, &uid_dbt, &vcard_dbt, DB_NEXT);
	}

	db_error = dbc->c_close (dbc);
	if (db_error != 0)
		g_warning ("db->c_close failed with %d", db_error);

	if (sexp)
		g_object_unref (sexp);

	return g_list_reverse (list);
}
예제 #3
0
파일: dn2id.c 프로젝트: cptaffe/openldap
int
hdb_dn2id_children(
	Operation *op,
	DB_TXN *txn,
	Entry *e )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	DB *db = bdb->bi_dn2id->bdi_db;
	DBT		key, data;
	DBC		*cursor;
	int		rc;
	ID		id;
	diskNode d;

	DBTzero(&key);
	key.size = sizeof(ID);
	key.data = &e->e_id;
	key.flags = DB_DBT_USERMEM;
	BDB_ID2DISK( e->e_id, &id );

	/* IDL cache is in host byte order */
	if ( bdb->bi_idl_cache_size ) {
		rc = bdb_idl_cache_get( bdb, db, &key, NULL );
		if ( rc != LDAP_NO_SUCH_OBJECT ) {
			return rc;
		}
	}

	key.data = &id;
	DBTzero(&data);
	data.data = &d;
	data.ulen = sizeof(d);
	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
	data.dlen = sizeof(d);

	rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
	if ( rc ) return rc;

	rc = cursor->c_get( cursor, &key, &data, DB_SET );
	if ( rc == 0 ) {
		db_recno_t dkids;
		rc = cursor->c_count( cursor, &dkids, 0 );
		if ( rc == 0 ) {
			BEI(e)->bei_dkids = dkids;
			if ( dkids < 2 ) rc = DB_NOTFOUND;
		}
	}
	cursor->c_close( cursor );
	return rc;
}
예제 #4
0
int
main(int argc, char *argv[])
{
	DB *dbp;
	DBC *curp;
	int ch, i, count;

	cleanup_test_dir();

	count = 100000;
	while ((ch = getopt(argc, argv, "c:")) != EOF)
		switch (ch) {
		case 'c':
			count = atoi(optarg);
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= optind;
	argv += optind;
	if (argc != 0)
		return (usage());

	/* Create the database. */
	DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
	dbp->set_errfile(dbp, stderr);

#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
	DB_BENCH_ASSERT(
	    dbp->open(dbp, NULL, "a", NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#else
	DB_BENCH_ASSERT(
	    dbp->open(dbp, "a", NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#endif

	/* Allocate a cursor count times. */
	TIMER_START;
	for (i = 0; i < count; ++i) {
		DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &curp, 0) == 0);
		DB_BENCH_ASSERT(curp->c_close(curp) == 0);
	}
	TIMER_STOP;

	printf("# %d cursor allocations\n", count);
	TIMER_DISPLAY(count);

	return (0);
}
예제 #5
0
파일: simple_txn.c 프로젝트: kanbang/Colt
/* Display all the stock quote information in the database. */
int
print_stocks(DB *dbp)
{
    DBC *dbc;
    DBT key, data;
#define	MAXKEYSIZE  10
#define	MAXDATASIZE 20
    char keybuf[MAXKEYSIZE + 1], databuf[MAXDATASIZE + 1];
    int ret, t_ret;
    u_int32_t keysize, datasize;

    if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) {
	dbp->err(dbp, ret, "can't open cursor");
	return (ret);
    }

    memset(&key, 0, sizeof(key));
    memset(&data, 0, sizeof(data));

    printf("\tSymbol\tPrice\n");
    printf("\t======\t=====\n");

    for (ret = dbc->c_get(dbc, &key, &data, DB_FIRST);
	ret == 0;
	ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) {
	keysize = key.size > MAXKEYSIZE ? MAXKEYSIZE : key.size;
	memcpy(keybuf, key.data, keysize);
	keybuf[keysize] = '\0';

	datasize = data.size >= MAXDATASIZE ? MAXDATASIZE : data.size;
	memcpy(databuf, data.data, datasize);
	databuf[datasize] = '\0';

	printf("\t%s\t%s\n", keybuf, databuf);
    }
    printf("\n");
    fflush(stdout);

    if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
	ret = t_ret;

    switch (ret) {
    case 0:
    case DB_NOTFOUND:
	return (0);
    default:
	return (ret);
    }
}
예제 #6
0
파일: bdb.c 프로젝트: w796933/bind99damp
static isc_result_t
bdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *n)
{
	int ret;
	char *type, *rdata;
	dns_ttl_t ttl;
	isc_consttextregion_t ttltext;
	DBC *c;
	DBT key, data;

	UNUSED(zone);

	if ((ret = ((DB *)dbdata)->cursor((DB *)dbdata, NULL, &c, 0)) != 0) {
		isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			       DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
			       isc_msgcat, ISC_MSGSET_GENERAL,
			       ISC_MSG_FAILED, "DB->cursor: %s",
			       db_strerror(ret));
		return ISC_R_FAILURE;
	}

	memset(&key, 0, sizeof(DBT));
	memset(&data, 0, sizeof(DBT));

	while (c->c_get(c, &key, &data, DB_NEXT) == 0) {
		((char *)key.data)[key.size] = 0;
		((char *)data.data)[data.size] = 0;
		ttltext.base = strtok((char *)data.data, " ");
		ttltext.length = strlen(ttltext.base);
		dns_ttl_fromtext((isc_textregion_t *)&ttltext, &ttl);
		type = strtok(NULL, " ");
		rdata = type + strlen(type) + 1;

		if (dns_sdb_putnamedrr(n, key.data, type, ttl, rdata) !=
		    ISC_R_SUCCESS) {
			isc_log_iwrite(dns_lctx,
				       DNS_LOGCATEGORY_DATABASE,
				       DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
				       isc_msgcat, ISC_MSGSET_GENERAL,
				       ISC_MSG_FAILED, "dns_sdb_putnamedrr");
			return ISC_R_FAILURE;
		}

	}

	c->c_close(c);
	return ISC_R_SUCCESS;
}
예제 #7
0
파일: db_operate.cpp 프로젝트: pkxpp/Study
int
update_trans_to_db(const char* pcszChinese, const char* pcszTrans){
	DBC 	*cursorp;
	DBT 	key, data;
	int	nRet = 0;
	char    szTransConverted[MAX_TRANS_LEN];
	
	memset(&key, 0, sizeof(DBT));
	memset(&data, 0, sizeof(DBT));

	/* Set up our DBTs */
	key.data = (void*)pcszChinese;
	key.size = (unsigned int)strlen(pcszChinese) + 1;
	/* Get the cursor */
	g_myBDB->cursor(g_myBDB, NULL, &cursorp, 0);
	if ( cursorp == NULL ) {
		write_log(LT_FILE, "Error: Can't get the cursor, when update "
				   "the translate of %s!\n", pcszChinese);
		return 0;
	}

	special_sign_convert(pcszTrans, szTransConverted, g_dbInfo.nLanguageType);
	
	/* Position the cursor */
	nRet = cursorp->c_get(cursorp, &key, &data, DB_SET);
	if (nRet == 0) {
		data.data = (void*)szTransConverted;
		data.size = (unsigned int)strlen(szTransConverted) + 1;
		cursorp->c_put(cursorp, &key, &data, DB_CURRENT);
	}
	else{
		write_log(LT_FILE, "Error: Can't find record %s, when update "
				   "its translate, try to insert it!\n",
				   pcszChinese);
		nRet = insert_to_db(pcszChinese, pcszTrans);
		goto exit;
	}

	write_log(LT_FILE, "Info: %s update success!\n", pcszChinese);

	nRet = 1;
 exit:
	/* Cursors must be closed */
	if ( cursorp != NULL ) 
		cursorp->c_close(cursorp); 
	
	return nRet;
}
// ------------------------------------------------------------------
int db_cursor_read_proc (DB *dbp,const char file_db[])
{
	int ret;
	int t_ret;
	DBC *dbcp = NULL;
	DBT key;
	DBT data;

	ret = dbp->cursor(dbp, NULL, &dbcp, 0);
	if (ret != 0) {
		dbp->err(dbp, ret, "%s", file_db);
	}
else
{
	cerr <<  "*** ccc ***\n";
	while (1) {
		memset(&key, 0, sizeof(key));
		memset(&data, 0, sizeof(data));

		ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT);

	if (ret == DB_NOTFOUND) {
//	fprintf (stderr, "*** DB_NOTFOUND ***\n");
		ret = 0;
		break;
		}
	else if (ret != 0) {
		dbp->err(dbp, ret, "%s", file_db);
		break;
        }

//        printf("%.*s\t%.*s\n", (int)key.size, (char *)key.data,
//               (int)data.size, (char *)data.data);

	json_record_display ((char *)key.data,(char *)data.data);
    }
	cerr << "*** fff ***\n";
}

	if (dbcp)
		{
		t_ret = dbcp->c_close(dbcp);
		if (t_ret != 0 && ret == 0)
		ret = t_ret;
		}

	return	ret;
}
예제 #9
0
bool Bigram::load_db(const char * dbfile){
    reset();

    /* create in memory db. */
    int ret = db_create(&m_db, NULL, 0);
    assert(ret == 0);

    ret = m_db->open(m_db, NULL, NULL, NULL,
                     DB_HASH, DB_CREATE, 0600);
    if ( ret != 0 )
        return false;

    /* load db into memory. */
    DB * tmp_db = NULL;
    ret = db_create(&tmp_db, NULL, 0);
    assert(ret == 0);

    ret = tmp_db->open(tmp_db, NULL, dbfile, NULL,
                       DB_HASH, DB_RDONLY, 0600);
    if ( ret != 0 )
        return false;

    DBC * cursorp = NULL;
    DBT key, data;
    /* Get a cursor */
    tmp_db->cursor(tmp_db, NULL, &cursorp, 0);

    /* Initialize our DBTs. */
    memset(&key, 0, sizeof(DBT));
    memset(&data, 0, sizeof(DBT));

    /* Iterate over the database, retrieving each record in turn. */
    while ((ret = cursorp->c_get(cursorp, &key, &data, DB_NEXT)) == 0) {
        int ret = m_db->put(m_db, NULL, &key, &data, 0);
        assert(ret == 0);
    }
    assert (ret == DB_NOTFOUND);

    /* Cursors must be closed */
    if ( cursorp != NULL )
        cursorp->c_close(cursorp);

    if ( tmp_db != NULL )
        tmp_db->close(tmp_db, 0);

    return true;
}
예제 #10
0
파일: data.c 프로젝트: Tayyib/uludag
char *
db_dump_profile(void)
{
	struct databases db;
	struct pack *p;
	DBC *cursor = NULL;
	DBT pair[2];
	int e;
	iks *xml = NULL, *item, *x;
	char *ret = NULL;

	memset(&pair[0], 0, sizeof(DBT) * 2);
	pair[1].flags = DB_DBT_MALLOC;

	if (open_env(&db, PROFILE_DB)) goto out;

	db.profile->cursor(db.profile, NULL, &cursor, 0);

	xml = iks_new("comarProfile");
	iks_insert_cdata(xml, "\n", 1);
	while ((e = cursor->c_get(cursor, &pair[0], &pair[1], DB_NEXT)) == 0) {
		char *t;
		size_t ts;
		item = iks_insert(xml, "item");
		iks_insert_cdata(iks_insert(item, "key"), pair[0].data, pair[0].size);
		p = pack_wrap(pair[1].data, pair[1].size);
		while (pack_get(p, &t, &ts)) {
			iks_insert_cdata(item, "\n", 1);
			x = iks_insert(item, "data");
			iks_insert_attrib(x, "key", t);
			pack_get(p, &t, &ts);
			iks_insert_cdata(iks_insert(x, "value"), t, ts);
		}
		pack_delete(p);
		iks_insert_cdata(xml, "\n", 1);
	}
	if (e != DB_NOTFOUND) {
		goto out;
	}

	ret = iks_string(NULL, xml);
out:
	if (cursor) cursor->c_close(cursor);
	close_env(&db);
	if (xml) iks_delete(xml);
	return ret;
}
예제 #11
0
int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
    chash * exist)
{
  DB * dbp;
  int r;
  DBC * dbcp;
  DBT db_key;
  DBT db_data;
  
  dbp = cache_db->internal_database;
 
#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
  r = dbp->cursor(dbp, NULL, &dbcp);
#else
  r = dbp->cursor(dbp, NULL, &dbcp, 0);
#endif  
  if (r != 0)
    return -1;
  
  memset(&db_key, 0, sizeof(db_key));
  memset(&db_data, 0, sizeof(db_data));
  
  while (1) {
    chashdatum hash_key;
    chashdatum hash_data;
    
    r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT);
    if (r != 0)
      break;
    
    hash_key.data = db_key.data;
    hash_key.len = db_key.size;

    r = chash_get(exist, &hash_key, &hash_data);
    if (r < 0) {
      r = dbcp->c_del(dbcp, 0);
      if (r != 0)
        return -1;
    }
  }
  
  r = dbcp->c_close(dbcp);
  if (r != 0)
    return -1;
  
  return 0;
}
예제 #12
0
void ReadFromDBAndPutInFile(FILE *outFile)
{
  pwr_tInt32 ret, sts;
  pwr_tUInt32 nrOfEvents = 0;
  sEvent *eventp;
  DBT data, key;
  DBC *dbcp;
  
  WriteColumnNames(outFile);
  
  /* Acquire a cursor for the database. */ 
  if ((ret = dataBaseP->cursor(dataBaseP, NULL, &dbcp, 0)) != 0) 
  {
    printf("error dataBaseP->cursor: %s\n", db_strerror(ret)); 
    exit(1);
  }

  /* Initialize the key/data return pair. */
  memset(&key, 0, sizeof(key));
  memset(&data, 0, sizeof(data));
  
  if((ret = dbcp->c_get(dbcp, &key, &data, DB_FIRST)) == 0)
  {
    eventp = data.data;
    sts = Write(eventp, outFile);
    nrOfEvents++;
  }
  
  while((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
  {
    eventp = data.data;
    sts = Write(eventp, outFile);
    nrOfEvents++;
  }
  if(ret != DB_NOTFOUND)
  {
    printf("error dbcp->c_get: %s\n", db_strerror(ret));
    printf("** Error reading post number %u, terminating\n", nrOfEvents);
    exit(1);
  }
  printf("-- Number of events written to file: %u\n", nrOfEvents);
  /*Close the cursor*/
  if((ret = dbcp->c_close(dbcp)) != 0)
  {
    printf("Error dbcp->c_close(): %s\n", db_strerror(ret));
  }       
}  
예제 #13
0
int bdb_last_id( BackendDB *be, DB_TXN *tid )
{
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	int rc;
	ID id = 0;
	unsigned char idbuf[sizeof(ID)];
	DBT key, data;
	DBC *cursor;

	DBTzero( &key );
	key.flags = DB_DBT_USERMEM;
	key.data = (char *) idbuf;
	key.ulen = sizeof( idbuf );

	DBTzero( &data );
	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;

	/* Get a read cursor */
	rc = bdb->bi_id2entry->bdi_db->cursor( bdb->bi_id2entry->bdi_db,
		tid, &cursor, 0 );

	if (rc == 0) {
		rc = cursor->c_get(cursor, &key, &data, DB_LAST);
		cursor->c_close(cursor);
	}

	switch(rc) {
	case DB_NOTFOUND:
		rc = 0;
		break;
	case 0:
		BDB_DISK2ID( idbuf, &id );
		break;

	default:
		Debug( LDAP_DEBUG_ANY,
			"=> bdb_last_id: get failed: %s (%d)\n",
			db_strerror(rc), rc, 0 );
		goto done;
	}

	bdb->bi_lastid = id;

done:
	return rc;
}
예제 #14
0
bool Bigram::save_db(const char * dbfile){
    DB * tmp_db = NULL;

    int ret = unlink(dbfile);
    if ( ret != 0 && errno != ENOENT)
        return false;

    ret = db_create(&tmp_db, NULL, 0);
    assert(ret == 0);

    if (NULL == tmp_db)
        return false;

    ret = tmp_db->open(tmp_db, NULL, dbfile, NULL,
                       DB_HASH, DB_CREATE, 0600);
    if ( ret != 0 )
        return false;

    DBC * cursorp = NULL;
    DBT key, data;
    /* Get a cursor */
    m_db->cursor(m_db, NULL, &cursorp, 0);

    if (NULL == cursorp)
        return false;

    /* Initialize our DBTs. */
    memset(&key, 0, sizeof(DBT));
    memset(&data, 0, sizeof(DBT));

    /* Iterate over the database, retrieving each record in turn. */
    while ((ret = cursorp->c_get(cursorp, &key, &data, DB_NEXT)) == 0) {
        int ret = tmp_db->put(tmp_db, NULL, &key, &data, 0);
        assert(ret == 0);
    }
    assert (ret == DB_NOTFOUND);

    /* Cursors must be closed */
    if ( cursorp != NULL )
        cursorp->c_close(cursorp);

    if ( tmp_db != NULL )
        tmp_db->close(tmp_db, 0);

    return true;
}
예제 #15
0
파일: oomindmap.c 프로젝트: M0nsteR/OOmnik
static int
ooMindMap_keys(struct ooMindMap *self,
	       mindmap_size_t  **ids,
	       mindmap_size_t    batch_size,
	       mindmap_size_t    batch_start)
{   DBT key, data;
    DB *dbp;
    DBC *dbcp;
    int ret;

    dbp = self->_storage;

    /* initialize the key/data pair */
    memset(&key, 0, sizeof(DBT));
    memset(&data, 0, sizeof(DBT));

    /* acquire a cursor for the database */
    if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
	dbp->err(dbp, ret, "DB->cursor");
	goto error;
    }

    /* TODO: batching */

    /* walk through the database and print out the key/data pairs. */
    while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
	printf("%.*s : %.*s\n",
	       (int)key.size, (char *)key.data,
	       (int)data.size, (char *)data.data);
    if (ret != DB_NOTFOUND)
    {	dbp->err(dbp, ret, "DBcursor->get");
	goto error;
    }

    /* close everything down */
    if ((ret = dbcp->c_close(dbcp)) != 0) {
	dbp->err(dbp, ret, "DBcursor->close");
	goto error;
    }

    return oo_OK;

error:	
    (void)dbp->close(dbp, 0);
    return oo_FAIL;
}
예제 #16
0
void DbPlugin::dump (QString &d, bool f)
{
  QFile outFile(d);
  if (! outFile.open(IO_WriteOnly))
    return;
  QTextStream outStream(&outFile);
  
  DBT key, data;
  DBC *cur;
  memset(&key, 0, sizeof(DBT));
  memset(&data, 0, sizeof(DBT));

  DBBar dbbar;
  memset(&dbbar, 0, sizeof(DBBar));
  data.data = &dbbar;
  data.ulen = sizeof(DBBar); 
  data.flags = DB_DBT_USERMEM;  

  db->cursor(db, NULL, &cur, 0);

  QFileInfo fi(symbol);

  while (! cur->c_get(cur, &key, &data, DB_NEXT))
  {
    if (f)
    {
      outStream << fi.fileName() << "," << (char *) key.data << "," << QString::number(dbbar.open) << ","
      << QString::number(dbbar.high) << "," << QString::number(dbbar.low) << "," 
      << QString::number(dbbar.close) << "," << QString::number(dbbar.volume, 'f', 0) << ","
      << QString::number(dbbar.oi) << "\n";
    }
    else
    {
      outStream << (char *) key.data << "=" << QString::number(dbbar.open) << ","
      << QString::number(dbbar.high) << "," << QString::number(dbbar.low) << "," 
      << QString::number(dbbar.close) << "," << QString::number(dbbar.volume, 'f', 0) << ","
      << QString::number(dbbar.oi) << "\n";
    }
  }
  cur->c_close(cur);

  outFile.close();
}
예제 #17
0
void DbPlugin::getLastBar (Bar &bar)
{
  DBT key, data;
  DBC *cur;
  memset(&key, 0, sizeof(DBT));
  memset(&data, 0, sizeof(DBT));

  DBBar dbbar;
  memset(&dbbar, 0, sizeof(DBBar));
  data.data = &dbbar;
  data.ulen = sizeof(DBBar); 
  data.flags = DB_DBT_USERMEM;  

  db->cursor(db, NULL, &cur, 0);
  cur->c_get(cur, &key, &data, DB_PREV);
  QString k = (char *) key.data;
  getBar(dbbar, k, bar);
  cur->c_close(cur);
}
예제 #18
0
void DBBase::dump (QString &d)
{
  QFile outFile(d);
  if (! outFile.open(QIODevice::WriteOnly))
    return;
  Q3TextStream outStream(&outFile);

  DBT key, data;
  DBC *cur;
  memset(&key, 0, sizeof(DBT));
  memset(&data, 0, sizeof(DBT));
  db->cursor(db, NULL, &cur, 0);

  while (! cur->c_get(cur, &key, &data, DB_NEXT))
    outStream << (char *) key.data << "=" << (char *) data.data << "\n";

  cur->c_close(cur);
  outFile.close();
}
예제 #19
0
int mail_cache_db_get_keys(struct mail_cache_db * cache_db,
    chash * keys)
{
  DB * dbp;
  int r;
  DBC * dbcp;
  DBT db_key;
  DBT db_data;
  
  dbp = cache_db->internal_database;
  
  r = dbp->cursor(dbp, NULL, &dbcp, 0);
  if (r != 0)
    return -1;
  
  memset(&db_key, 0, sizeof(db_key));
  memset(&db_data, 0, sizeof(db_data));
  
  while (1) {
    chashdatum hash_key;
    chashdatum hash_data;
    
    r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT);
    if (r != 0)
      break;
    
    hash_key.data = db_key.data;
    hash_key.len = db_key.size;
    hash_data.data = NULL;
    hash_data.len = 0;
    
    r = chash_set(keys, &hash_key, &hash_data, NULL);
    if (r < 0) {
      return -1;
    }
  }
  
  r = dbcp->c_close(dbcp);
  if (r != 0)
    return -1;
  
  return 0;
}
예제 #20
0
local void walk_db(int (*func)(DBT *key, DBT *val), int write)
{
    DBC *cursor;
    DBT key, val;

    if (db->cursor(db, NULL, &cursor, write ? DB_WRITECURSOR : 0))
    {
        if (write)
            fputs("couldn't get db cursor for writing. is the db read-only?\n", stderr);
        else
            fputs("couldn't get db cursor.\n", stderr);
        return;
    }

    memset(&key, 0, sizeof(key));
    memset(&val, 0, sizeof(val));
    while (cursor->c_get(cursor, &key, &val, DB_NEXT) == 0)
        if (func(&key, &val))
            cursor->c_del(cursor, 0);

    cursor->c_close(cursor);
}
예제 #21
0
void DbPlugin::getSearchBar (QDateTime &startDate, Bar &bar)
{
  DBT key, data;
  DBC *cur;
  memset(&key, 0, sizeof(DBT));
  memset(&data, 0, sizeof(DBT));

  DBBar dbbar;
  memset(&dbbar, 0, sizeof(DBBar));
  data.data = &dbbar;
  data.ulen = sizeof(DBBar); 
  data.flags = DB_DBT_USERMEM;  

  db->cursor(db, NULL, &cur, 0);

  QString s = startDate.toString("yyyyMMddhhmmss");
  key.data = (char *) s.latin1();
  key.size = s.length() + 1;
  cur->c_get(cur, &key, &data, DB_SET_RANGE);
  s = (char *) key.data;
  getBar(dbbar, s, bar);
  cur->c_close(cur);
}
예제 #22
0
static void scanscan_lwc (void) {
    int r;
    int counter=0;
    for (counter=0; counter<n_experiments; counter++) {
        struct extra_count e = {0,0};
        double prevtime = gettime();
        DBC *dbc;
        r = db->cursor(db, tid, &dbc, 0);                           assert(r==0);
        u_int32_t f_flags = 0;
        if (prelockflag && (counter || prelock)) {
            f_flags |= lock_flag;
        }
        long rowcounter=0;
        while (0 == (r = dbc->c_getf_next(dbc, f_flags, counttotalbytes, &e))) {
            rowcounter++;
            if (limitcount>0 && rowcounter>=limitcount) break;
        }
        r = dbc->c_close(dbc);                                      assert(r==0);
        double thistime = gettime();
        double tdiff = thistime-prevtime;
        printf("LWC Scan %lld bytes (%d rows) in %9.6fs at %9fMB/s\n", e.totalbytes, e.rowcounter, tdiff, 1e-6*e.totalbytes/tdiff);
    }
}
예제 #23
0
/* This function initializes the trees at startup time. */
int bdb_build_tree(
	Backend *be
)
{
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	int rc;
	DBC *cursor;
	DBT key, data;
	ID id;
	idNode *node;

	bdb->bi_tree = NULL;

	rc = bdb->bi_id2parent->bdi_db->cursor(
		bdb->bi_id2parent->bdi_db, NULL, &cursor,
		bdb->bi_db_opflags );
	if( rc != 0 ) {
		return NOID;
	}

	DBTzero( &key );
	DBTzero( &data );
	key.data = (char *)&id;
	key.ulen = sizeof( id );
	key.flags = DB_DBT_USERMEM;
	data.flags = DB_DBT_MALLOC;

	while (cursor->c_get( cursor, &key, &data, DB_NEXT ) == 0) {
		bdb_add_node( id, data.data, bdb );
	}
	cursor->c_close( cursor );

	rc = avl_apply(bdb->bi_tree, bdb_insert_kid, bdb->bi_tree,
		-1, AVL_INORDER );

	return rc;
}
예제 #24
0
파일: storage_bdb.c 프로젝트: ailidani/PMDS
/*@
 * Walk through the database and return the highest iid we have seen. 
 * If this is a RECNO database this can probably be done more cheaply
 * but for now we will make this usable regardless of the index impl
 */
iid_t 
storage_get_max_iid(struct storage * s)
{
	int ret;
	DB *dbp = s->db;
	DBC *dbcp;
	DBT key, data;
	iid_t max_iid = 0;
	
	/* Acquire a cursor for the database. */
	if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
		dbp->err(dbp, ret, "DB->cursor");
		return (1);
	}
	
	/* Re-initialize the key/data pair. */ 
	memset(&key, 0, sizeof(key));
	memset(&data, 0, sizeof(data));
	
	/* Walk through the database and print out the key/data pairs. */
	while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
		assert(data.size = sizeof(iid_t));
		max_iid = *(iid_t *)key.data;
	}
	
	if (ret != DB_NOTFOUND) {
		dbp->err(dbp, ret, "DBcursor->get");
		return 0;
	}
	
	/* Close the cursor. */
	if ((ret = dbcp->c_close(dbcp)) != 0) {
		dbp->err(dbp, ret, "DBcursor->close");
	}
	return (max_iid);
}
예제 #25
0
static void
do_dump_triplets()
{
    DBC *dbcp;
    int rc;
    DBT key = { 0 },
        data = { 0 };
    rc = db->cursor(db, 0, &dbcp, 0);
    if (rc)
        fprintf(stderr, "DBD-%d: db->cursor failed: %s\n",
                rc, db_strerror(rc));
    else {
        while ((rc = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
            const char *s = key.data;
            const struct triplet_data *t = data.data;
            printf("%d\t", t->crypted);
            printf("%s\t", s);
            s += strlen(s) + 1;
            printf("%s\t", s);
            s += strlen(s) + 1;
            fwrite(s, 1, key.size - (s - (char *)key.data), stdout);
            putchar('\t');
            write_ctime(&t->create_time);
            putchar('\t');
            write_ctime(&t->access_time);
            printf("\t%lu\t%lu\n", t->block_count, t->pass_count);
        }
        if (rc != DB_NOTFOUND)
            fprintf(stderr, "DBD-%d: dbcp->c_get failed: %s\n",
                    rc, db_strerror(rc));
        rc = dbcp->c_close(dbcp);
        if (rc)
            fprintf(stderr, "DBD-%d: dbcp->c_close failed: %s\n",
                    rc, db_strerror(rc));
    }
}
예제 #26
0
void
print_distinct(int cutoff)
{
	struct hashtable *hash;
	DBC *dbcp;
	DBT key, data;
	int ret;

	//create_hashtable(1, hashfromkey_url, equalkeys_url);


	memset(&key, 0, sizeof(key));
	memset(&data, 0, sizeof(data));

	/* Acquire a cursor for the database. */
	if ((ret = maindb->cursor(maindb, NULL, &dbcp, 0)) != 0) {
		maindb->err(maindb, ret, "DB->cursor");
		exit(1);
	}

	/* Walk through the database and print out the key/data pairs. */
	while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
		struct in_addr in;
		struct dbkey dbkey;
		struct dbkey dbkey2;
		struct dbkey dbkey3;
		unsigned int num;
		unsigned int i;
		char *url;
		DBT key2, data2;
		DBT key3, data3;
		char url2[10240];

		num = *(unsigned int *)data.data;
		memcpy(&dbkey, key.data, key.size);

		if (dbkey.num != 0)
			continue;
		in.s_addr = dbkey.addr;

		if (num < cutoff)
			continue;
		printf("Got %d record for %s\n", num, inet_ntoa(in));
#if 0
		hash = create_hashtable(10, hashfromkey_url, equalkeys_url);
		for (i = 1; i <= num; i++) {
			char *hashkey;
			dbkey2.addr = in.s_addr;
			if (num > 1)
				dbkey2.num = 2;
			else
				dbkey2.num = i;

			memset(&key2, 0, sizeof(key2));
			key2.data = &dbkey2;
			key2.size = sizeof(dbkey2);
			memset(&data2, 0, sizeof(data2));
			//data2.data = url2;
			//data2.size = sizeof(url2);

			if ((ret = maindb->get(maindb, NULL, &key2, &data2, 0) != 0)) {
				maindb->err(maindb, ret, "DBcursor->get");
				exit(1);
			}

			strncpy(url2, data2.data, data2.size);
			url2[data2.size] = '\0';
			//printf("\tFound: %d\n", data2.size);
			//printf("\tFound: %s\n", url2);

			hashkey = strdup(url2);
			if (hashkey == NULL)
				err(1, "Oops, hashkey is null");
			if (!hashtable_search(hash, url2)) {
				hashkey = strdup(url2);
				if (hashkey == NULL)
					err(1, "Oops, hashkey is null");

				hashtable_insert(hash, hashkey, &fakeval);
			}

		}
		if (num != hashtable_count(hash) && hashtable_count(hash) != 1) {
			printf("%d is really %d\n", num, hashtable_count(hash));
		}
		hashtable_destroy(hash, 0);
#endif
	}
	if (ret != DB_NOTFOUND) {
		maindb->err(maindb, ret, "DBcursor->c_get");
		exit(1);
	}

	if ((ret = dbcp->c_close(dbcp)) != 0)
		maindb->err(maindb, ret, "DBcursor->close");

}
예제 #27
0
void
print_all(void)
{
	struct hashtable *hash;
	DBC *dbcp;
	DBT key, data;
	int ret;

	create_hashtable(1, hashfromkey_url, equalkeys_url);


	memset(&key, 0, sizeof(key));
	memset(&data, 0, sizeof(data));

	/* Acquire a cursor for the database. */
	if ((ret = maindb->cursor(maindb, NULL, &dbcp, 0)) != 0) {
		maindb->err(maindb, ret, "DB->cursor");
		exit(1);
	}

	/* Walk through the database and print out the key/data pairs. */
	while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
		struct in_addr in;
		struct dbkey dbkey;
		struct dbkey dbkey2;
		struct dbkey dbkey3;
		unsigned int num;
		unsigned int i;
		char *url;
		DBT key2, data2;
		DBT key3, data3;
		char url2[10240];

		num = *(unsigned int *)data.data;
		memcpy(&dbkey, key.data, key.size);

		if (dbkey.num != 0)
			continue;
		in.s_addr = dbkey.addr;

		printf("Got %d record for %s\n", num, inet_ntoa(in));
		for (i = 1; i <= num; i++) {
			char *hashkey;
			dbkey2.addr = in.s_addr;
			if (num > 1)
				dbkey2.num = 2;
			else
				dbkey2.num = i;

			memset(&key2, 0, sizeof(key2));
			key2.data = &dbkey2;
			key2.size = sizeof(dbkey2);
			memset(&data2, 0, sizeof(data2));
			//data2.data = url2;
			//data2.size = sizeof(url2);

			if ((ret = maindb->get(maindb, NULL, &key2, &data2, 0) != 0)) {
				maindb->err(maindb, ret, "DBcursor->get");
				exit(1);
			}

			strncpy(url2, data2.data, data2.size);
			url2[data2.size] = '\0';
			//printf("\tFound: %d\n", data2.size);
			printf("\tFound: %s\n", url2);
		}
	}
	if (ret != DB_NOTFOUND) {
		maindb->err(maindb, ret, "DBcursor->get");
		exit(1);
	}

	if ((ret = dbcp->c_close(dbcp)) != 0)
		maindb->err(maindb, ret, "DBcursor->close");

}
예제 #28
0
파일: idl.c 프로젝트: 1ack/Impala
int
bdb_idl_delete_key(
	BackendDB	*be,
	DB			*db,
	DB_TXN		*tid,
	DBT			*key,
	ID			id )
{
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	int	rc;
	DBT data;
	DBC *cursor;
	ID lo, hi, tmp, nid, nlo, nhi;
	char *err;

	{
		char buf[16];
		Debug( LDAP_DEBUG_ARGS,
			"bdb_idl_delete_key: %lx %s\n", 
			(long) id, bdb_show_key( key, buf ), 0 );
	}
	assert( id != NOID );

	if ( bdb->bi_idl_cache_size ) {
		bdb_idl_cache_del( bdb, db, key );
	}

	BDB_ID2DISK( id, &nid );

	DBTzero( &data );
	data.data = &tmp;
	data.size = sizeof( id );
	data.ulen = data.size;
	data.flags = DB_DBT_USERMEM;

	rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
	if ( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
			"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
		return rc;
	}
	/* Fetch the first data item for this key, to see if it
	 * exists and if it's a range.
	 */
	rc = cursor->c_get( cursor, key, &data, DB_SET );
	err = "c_get";
	if ( rc == 0 ) {
		if ( tmp != 0 ) {
			/* Not a range, just delete it */
			if (tmp != nid) {
				/* position to correct item */
				tmp = nid;
				rc = cursor->c_get( cursor, key, &data, DB_GET_BOTH );
				if ( rc != 0 ) {
					err = "c_get id";
					goto fail;
				}
			}
			rc = cursor->c_del( cursor, 0 );
			if ( rc != 0 ) {
				err = "c_del id";
				goto fail;
			}
		} else {
			/* It's a range, see if we need to rewrite
			 * the boundaries
			 */
			data.data = &nlo;
			rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
			if ( rc != 0 ) {
				err = "c_get lo";
				goto fail;
			}
			BDB_DISK2ID( &nlo, &lo );
			data.data = &nhi;
			rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
			if ( rc != 0 ) {
				err = "c_get hi";
				goto fail;
			}
			BDB_DISK2ID( &nhi, &hi );
			if ( id == lo || id == hi ) {
				if ( id == lo ) {
					id++;
					lo = id;
				} else if ( id == hi ) {
					id--;
					hi = id;
				}
				if ( lo >= hi ) {
				/* The range has collapsed... */
					rc = db->del( db, tid, key, 0 );
					if ( rc != 0 ) {
						err = "del";
						goto fail;
					}
				} else {
					if ( id == lo ) {
						/* reposition on lo slot */
						data.data = &nlo;
						cursor->c_get( cursor, key, &data, DB_PREV );
					}
					rc = cursor->c_del( cursor, 0 );
					if ( rc != 0 ) {
						err = "c_del";
						goto fail;
					}
				}
				if ( lo <= hi ) {
					BDB_ID2DISK( id, &nid );
					data.data = &nid;
					rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
					if ( rc != 0 ) {
						err = "c_put lo/hi";
						goto fail;
					}
				}
			}
		}
	} else {
		/* initial c_get failed, nothing was done */
fail:
		if ( rc != DB_NOTFOUND ) {
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
			"%s failed: %s (%d)\n", err, db_strerror(rc), rc );
		}
		cursor->c_close( cursor );
		return rc;
	}
	rc = cursor->c_close( cursor );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			"=> bdb_idl_delete_key: c_close failed: %s (%d)\n",
			db_strerror(rc), rc, 0 );
	}

	return rc;
}
예제 #29
0
파일: idl.c 프로젝트: 1ack/Impala
int
bdb_idl_insert_key(
	BackendDB	*be,
	DB			*db,
	DB_TXN		*tid,
	DBT			*key,
	ID			id )
{
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	int	rc;
	DBT data;
	DBC *cursor;
	ID lo, hi, nlo, nhi, nid;
	char *err;

	{
		char buf[16];
		Debug( LDAP_DEBUG_ARGS,
			"bdb_idl_insert_key: %lx %s\n", 
			(long) id, bdb_show_key( key, buf ), 0 );
	}

	assert( id != NOID );

	DBTzero( &data );
	data.size = sizeof( ID );
	data.ulen = data.size;
	data.flags = DB_DBT_USERMEM;

	BDB_ID2DISK( id, &nid );

	rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
	if ( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
			"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
		return rc;
	}
	data.data = &nlo;
	/* Fetch the first data item for this key, to see if it
	 * exists and if it's a range.
	 */
	rc = cursor->c_get( cursor, key, &data, DB_SET );
	err = "c_get";
	if ( rc == 0 ) {
		if ( nlo != 0 ) {
			/* not a range, count the number of items */
			db_recno_t count;
			rc = cursor->c_count( cursor, &count, 0 );
			if ( rc != 0 ) {
				err = "c_count";
				goto fail;
			}
			if ( count >= BDB_IDL_DB_MAX ) {
			/* No room, convert to a range */
				DBT key2 = *key;
				db_recno_t i;

				key2.dlen = key2.ulen;
				key2.flags |= DB_DBT_PARTIAL;

				BDB_DISK2ID( &nlo, &lo );
				data.data = &nhi;

				rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_NODUP );
				if ( rc != 0 && rc != DB_NOTFOUND ) {
					err = "c_get next_nodup";
					goto fail;
				}
				if ( rc == DB_NOTFOUND ) {
					rc = cursor->c_get( cursor, key, &data, DB_LAST );
					if ( rc != 0 ) {
						err = "c_get last";
						goto fail;
					}
				} else {
					rc = cursor->c_get( cursor, key, &data, DB_PREV );
					if ( rc != 0 ) {
						err = "c_get prev";
						goto fail;
					}
				}
				BDB_DISK2ID( &nhi, &hi );
				/* Update hi/lo if needed, then delete all the items
				 * between lo and hi
				 */
				if ( id < lo ) {
					lo = id;
					nlo = nid;
				} else if ( id > hi ) {
					hi = id;
					nhi = nid;
				}
				data.data = &nid;
				/* Don't fetch anything, just position cursor */
				data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
				data.dlen = data.ulen = 0;
				rc = cursor->c_get( cursor, key, &data, DB_SET );
				if ( rc != 0 ) {
					err = "c_get 2";
					goto fail;
				}
				rc = cursor->c_del( cursor, 0 );
				if ( rc != 0 ) {
					err = "c_del range1";
					goto fail;
				}
				/* Delete all the records */
				for ( i=1; i<count; i++ ) {
					rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_DUP );
					if ( rc != 0 ) {
						err = "c_get next_dup";
						goto fail;
					}
					rc = cursor->c_del( cursor, 0 );
					if ( rc != 0 ) {
						err = "c_del range";
						goto fail;
					}
				}
				/* Store the range marker */
				data.size = data.ulen = sizeof(ID);
				data.flags = DB_DBT_USERMEM;
				nid = 0;
				rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
				if ( rc != 0 ) {
					err = "c_put range";
					goto fail;
				}
				nid = nlo;
				rc = cursor->c_put( cursor, key, &data, DB_KEYLAST );
				if ( rc != 0 ) {
					err = "c_put lo";
					goto fail;
				}
				nid = nhi;
				rc = cursor->c_put( cursor, key, &data, DB_KEYLAST );
				if ( rc != 0 ) {
					err = "c_put hi";
					goto fail;
				}
			} else {
			/* There's room, just store it */
				goto put1;
			}
		} else {
			/* It's a range, see if we need to rewrite
			 * the boundaries
			 */
			hi = id;
			data.data = &nlo;
			rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
			if ( rc != 0 ) {
				err = "c_get lo";
				goto fail;
			}
			BDB_DISK2ID( &nlo, &lo );
			if ( id > lo ) {
				data.data = &nhi;
				rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
				if ( rc != 0 ) {
					err = "c_get hi";
					goto fail;
				}
				BDB_DISK2ID( &nhi, &hi );
			}
			if ( id < lo || id > hi ) {
				/* Delete the current lo/hi */
				rc = cursor->c_del( cursor, 0 );
				if ( rc != 0 ) {
					err = "c_del";
					goto fail;
				}
				data.data = &nid;
				rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
				if ( rc != 0 ) {
					err = "c_put lo/hi";
					goto fail;
				}
			}
		}
	} else if ( rc == DB_NOTFOUND ) {
put1:		data.data = &nid;
		rc = cursor->c_put( cursor, key, &data, DB_NODUPDATA );
		/* Don't worry if it's already there */
		if ( rc != 0 && rc != DB_KEYEXIST ) {
			err = "c_put id";
			goto fail;
		}
	} else {
		/* initial c_get failed, nothing was done */
fail:
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
			"%s failed: %s (%d)\n", err, db_strerror(rc), rc );
		cursor->c_close( cursor );
		return rc;
	}
	/* If key was added (didn't already exist) and using IDL cache,
	 * update key in IDL cache.
	 */
	if ( !rc && bdb->bi_idl_cache_max_size ) {
		bdb_idl_cache_add_id( bdb, db, key, id );
	}
	rc = cursor->c_close( cursor );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
			"c_close failed: %s (%d)\n",
			db_strerror(rc), rc, 0 );
	}
	return rc;
}
예제 #30
0
파일: idl.c 프로젝트: 1ack/Impala
int
bdb_idl_fetch_key(
	BackendDB	*be,
	DB			*db,
	DB_TXN		*txn,
	DBT			*key,
	ID			*ids,
	DBC                     **saved_cursor,
	int                     get_flag )
{
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	int rc;
	DBT data, key2, *kptr;
	DBC *cursor;
	ID *i;
	void *ptr;
	size_t len;
	int rc2;
	int flags = bdb->bi_db_opflags | DB_MULTIPLE;
	int opflag;

	/* If using BerkeleyDB 4.0, the buf must be large enough to
	 * grab the entire IDL in one get(), otherwise BDB will leak
	 * resources on subsequent get's.  We can safely call get()
	 * twice - once for the data, and once to get the DB_NOTFOUND
	 * result meaning there's no more data. See ITS#2040 for details.
	 * This bug is fixed in BDB 4.1 so a smaller buffer will work if
	 * stack space is too limited.
	 *
	 * configure now requires Berkeley DB 4.1.
	 */
#if DB_VERSION_FULL < 0x04010000
#	define BDB_ENOUGH 5
#else
	/* We sometimes test with tiny IDLs, and BDB always wants buffers
	 * that are at least one page in size.
	 */
# if BDB_IDL_DB_SIZE < 4096
#   define BDB_ENOUGH 2048
# else
#	define BDB_ENOUGH 1
# endif
#endif
	ID buf[BDB_IDL_DB_SIZE*BDB_ENOUGH];

	char keybuf[16];

	Debug( LDAP_DEBUG_ARGS,
		"bdb_idl_fetch_key: %s\n", 
		bdb_show_key( key, keybuf ), 0, 0 );

	assert( ids != NULL );

	if ( saved_cursor && *saved_cursor ) {
		opflag = DB_NEXT;
	} else if ( get_flag == LDAP_FILTER_GE ) {
		opflag = DB_SET_RANGE;
	} else if ( get_flag == LDAP_FILTER_LE ) {
		opflag = DB_FIRST;
	} else {
		opflag = DB_SET;
	}

	/* only non-range lookups can use the IDL cache */
	if ( bdb->bi_idl_cache_size && opflag == DB_SET ) {
		rc = bdb_idl_cache_get( bdb, db, key, ids );
		if ( rc != LDAP_NO_SUCH_OBJECT ) return rc;
	}

	DBTzero( &data );

	data.data = buf;
	data.ulen = sizeof(buf);
	data.flags = DB_DBT_USERMEM;

	/* If we're not reusing an existing cursor, get a new one */
	if( opflag != DB_NEXT ) {
		rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
				"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
			return rc;
		}
	} else {
		cursor = *saved_cursor;
	}
	
	/* If this is a LE lookup, save original key so we can determine
	 * when to stop. If this is a GE lookup, save the key since it
	 * will be overwritten.
	 */
	if ( get_flag == LDAP_FILTER_LE || get_flag == LDAP_FILTER_GE ) {
		DBTzero( &key2 );
		key2.flags = DB_DBT_USERMEM;
		key2.ulen = sizeof(keybuf);
		key2.data = keybuf;
		key2.size = key->size;
		AC_MEMCPY( keybuf, key->data, key->size );
		kptr = &key2;
	} else {
		kptr = key;
	}
	len = key->size;
	rc = cursor->c_get( cursor, kptr, &data, flags | opflag );

	/* skip presence key on range inequality lookups */
	while (rc == 0 && kptr->size != len) {
		rc = cursor->c_get( cursor, kptr, &data, flags | DB_NEXT_NODUP );
	}
	/* If we're doing a LE compare and the new key is greater than
	 * our search key, we're done
	 */
	if (rc == 0 && get_flag == LDAP_FILTER_LE && memcmp( kptr->data,
		key->data, key->size ) > 0 ) {
		rc = DB_NOTFOUND;
	}
	if (rc == 0) {
		i = ids;
		while (rc == 0) {
			u_int8_t *j;

			DB_MULTIPLE_INIT( ptr, &data );
			while (ptr) {
				DB_MULTIPLE_NEXT(ptr, &data, j, len);
				if (j) {
					++i;
					BDB_DISK2ID( j, i );
				}
			}
			rc = cursor->c_get( cursor, key, &data, flags | DB_NEXT_DUP );
		}
		if ( rc == DB_NOTFOUND ) rc = 0;
		ids[0] = i - ids;
		/* On disk, a range is denoted by 0 in the first element */
		if (ids[1] == 0) {
			if (ids[0] != BDB_IDL_RANGE_SIZE) {
				Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
					"range size mismatch: expected %d, got %ld\n",
					BDB_IDL_RANGE_SIZE, ids[0], 0 );
				cursor->c_close( cursor );
				return -1;
			}
			BDB_IDL_RANGE( ids, ids[2], ids[3] );
		}
		data.size = BDB_IDL_SIZEOF(ids);
	}

	if ( saved_cursor && rc == 0 ) {
		if ( !*saved_cursor )
			*saved_cursor = cursor;
		rc2 = 0;
	}
	else
		rc2 = cursor->c_close( cursor );
	if (rc2) {
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
			"close failed: %s (%d)\n", db_strerror(rc2), rc2, 0 );
		return rc2;
	}

	if( rc == DB_NOTFOUND ) {
		return rc;

	} else if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
			"get failed: %s (%d)\n",
			db_strerror(rc), rc, 0 );
		return rc;

	} else if ( data.size == 0 || data.size % sizeof( ID ) ) {
		/* size not multiple of ID size */
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
			"odd size: expected %ld multiple, got %ld\n",
			(long) sizeof( ID ), (long) data.size, 0 );
		return -1;

	} else if ( data.size != BDB_IDL_SIZEOF(ids) ) {
		/* size mismatch */
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
			"get size mismatch: expected %ld, got %ld\n",
			(long) ((1 + ids[0]) * sizeof( ID )), (long) data.size, 0 );
		return -1;
	}

	if ( bdb->bi_idl_cache_max_size ) {
		bdb_idl_cache_put( bdb, db, key, ids, rc );
	}

	return rc;
}