Beispiel #1
0
int userToSubname_deletecol(struct userToSubnameDbFormat *userToSubnameDb,char subname[]) {
	DBC *cursorp;
	DBT key, data;
	int ret;

	debug("userToSubname_deletecol: deleting \"%s\"", subname);

	/* Get a cursor */
	(*userToSubnameDb).dbp->cursor((*userToSubnameDb).dbp, NULL, &cursorp, 0);

	//resetter minne
        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) {
    	    /* Do interesting things with the DBTs here. */
	    if (!strcmp(subname, data.data))
		{
		    debug("Deleting %s->%s (ret=%i)", (char*)key.data, (char*)data.data, cursorp->c_del(cursorp, 0));
		}
	    else
		{
		    debug("Keeping %s->%s", (char*)key.data, (char*)data.data);
		}
	}

	/* Close the cursor */
	if (cursorp != NULL) {
		cursorp->c_close(cursorp);
	}

	return 1;

}
Beispiel #2
0
/* Silently does nothing if the key/value isn't found.
   Can't use auto-commit here! */
int db_del_kv(DB *db, DB_TXN *tid, 
	      unsigned char *key, u_int32_t key_size,
	      unsigned char *value, u_int32_t value_size) {
  DBT DBTKey, DBTValue;
  DBC *cursor;
  int ret, c_ret;

  memset(&DBTKey, 0, sizeof(DBT));
  DBTKey.data = key;
  DBTKey.size = key_size;
  memset(&DBTValue, 0, sizeof(DBT));
  DBTValue.data = value;
  DBTValue.size = value_size;
  
  if ((ret = db->cursor(db, tid, &cursor, 0)) != 0)
    return ret;

  if ((ret = cursor->c_get(cursor, &DBTKey, &DBTValue, DB_GET_BOTH)) != 0)
    goto fail;

  ret = cursor->c_del(cursor, 0);

 fail:
  if ((c_ret = cursor->c_close(cursor)) != 0)
    return c_ret;
  return ret;
}
Beispiel #3
0
Datei: auth.c Projekt: Jc2k/exact
void auth_db_clean(int sig) {
    DBC *dbc;
    DBT key, data;
    int ret;
    time_t now=time(NULL);
    time_t max=(time_t)conffile_param_int("timeout");

    logger(LOG_NOTICE, "cleaning db file\n");
    // apparently i should use DB_WRITECURSOR as a flag here
    // but the version 3 db barfs on me when i do that
    if((ret = db->cursor(db, NULL, &dbc, 0)) != 0) {
        db->err(db, ret, "opening cursor");
        exit(22);
    }
    memset(&key, 0, sizeof(key));
    memset(&data, 0, sizeof(data));
    while((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) ==0) {
        time_t then = (time_t)data.data;
        if(now - then > max) {
            if((ret = dbc->c_del(dbc, 0)) != 0) {
                db->err(db, ret, "deleting key");
                exit(22);
            }
        }
    }
    logger(LOG_DEBUG,"Finished cleaning cycle\n");
}
Beispiel #4
0
static int dbiCursorDel(dbiCursor dbc, DBT * key, DBT * data, unsigned int flags)
{
    int rc = EINVAL;
    int sane = (key->data != NULL && key->size > 0);

    if (dbc && sane) {
	DBC * cursor = dbc->cursor;
	int _printit;
	rpmdb rdb = dbc->dbi->dbi_rpmdb;
	rpmswEnter(&rdb->db_delops, 0);

	/* XXX TODO: insure that cursor is positioned with duplicates */
	rc = cursor->c_get(cursor, key, data, DB_SET);
	/* XXX DB_NOTFOUND can be returned */
	_printit = (rc == DB_NOTFOUND ? 0 : _debug);
	rc = cvtdberr(dbc->dbi, "dbcursor->c_get", rc, _printit);

	if (rc == 0) {
	    rc = cursor->c_del(cursor, flags);
	    rc = cvtdberr(dbc->dbi, "dbcursor->c_del", rc, _debug);
	}
	rpmswExit(&rdb->db_delops, data->size);
    }
    return rc;
}
Beispiel #5
0
static void
run_expiry()
{
    DBC *dbcp;
    int rc;
    time_t now;
    unsigned int count = 0;
    /* Cursor operations can hold several locks and therefore deadlock
       so don't run expiry if deadlock detection does not work
       http://www.oracle.com/technology/documentation/berkeley-db/db/ref/lock/notxn.html */
    if (db == 0 || deadlock_detect == 0)
        return;
    if (time(&now) == (time_t)-1) {
        syslog(LOG_ERR, "time failed during run_expiry");
        return;
    }
    muffle_error++;
    if (rc = db->cursor(db, 0, &dbcp, 0))
        log_db_error("db->cursor failed during expiry run", rc);
    else {
        DBT key = { 0 };
        while ((rc = dbcp->c_get(dbcp, &key, &dbdata, DB_NEXT | DB_RMW)) == 0) {
            time_t ref_time;
            double age_max, age;
            if (triplet_data.pass_count) {
                ref_time = triplet_data.access_time;
                age_max = pass_max_idle;
            }
            else {
                ref_time = triplet_data.create_time;
                age_max = bloc_max_idle;
            }
            age = difftime(now, ref_time);
            if (age > age_max) {
                if (opt_verbose)
                    syslog(LOG_INFO, "Expiring %s %s after %.0f seconds idle",
                           key.data,
                           triplet_data.pass_count ? "pass" : "block", age);
                if (rc = dbcp->c_del(dbcp, 0))
                    log_db_error("dbcp->c_del failed", rc);
                else
                    count++;
            }
        }
        if (rc == DB_LOCK_DEADLOCK)
            syslog(LOG_DEBUG, "skipping concurrent expiry avoids "
                   "deadlocks and unnecessary work");
        else if (rc != DB_NOTFOUND)
            log_db_error("dbcp->c_get failed", rc);
        if (rc = dbcp->c_close(dbcp))
            log_db_error("dbcp->c_close failed", rc);
    }
    muffle_error--;
    if (count)
        syslog(LOG_NOTICE, "Expired %u triplets", count);
}
Beispiel #6
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;
}
Beispiel #7
0
int Dbc::del(u_int32_t flags_arg)
{
    DBC *cursor = this;
    int err;

    if ((err = cursor->c_del(cursor, flags_arg)) != 0) {

        // DB_KEYEMPTY is a "normal" return, so should not be
        // thrown as an error
        //
        if (err != DB_KEYEMPTY) {
            DB_ERROR("Db::del", err);
            return err;
        }
    }
    return 0;
}
Beispiel #8
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);
}
Beispiel #9
0
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;
}
/*
_bdb_delete_cursor -- called from bdb_delete when the query involves operators
  other than equal '='. Adds support for queries like this:
	DELETE from SomeTable WHERE _k[0] < _v[0]
  In this case, the keys _k are not the actually schema keys, so we need to
  iterate via cursor to perform this operation.
*/
int _bdb_delete_cursor(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    db_res_t* _r   = NULL;
    char kbuf[MAX_ROW_SIZE];
    char dbuf[MAX_ROW_SIZE];
    int i, ret, klen=MAX_ROW_SIZE;
    DBT key, data;
    DB *db;
    DBC *dbcp;
    int *lkey=NULL;
    str s;

    i = ret = 0;

    if ((!_h) || !CON_TABLE(_h))
        return -1;

    s.s = (char*)CON_TABLE(_h);
    s.len = strlen(CON_TABLE(_h));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -3;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -4;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("DELETE by cursor in %.*s\n", _tp->name.len, _tp->name.s );
#endif

    if(_k)
    {   lkey = bdb_get_colmap(_tp, _k, _n);
        if(!lkey)
        {   ret = -1;
            goto error;
        }
    }

    /* create an empty db_res_t which gets returned even if no result */
    _r = db_new_result();
    if (!_r)
    {   LM_ERR("no memory for result \n");
    }

    RES_ROW_N(_r) = 0;

    /* fill in the col part of db_res_t */
    if ((ret = bdb_get_columns(_tp, _r, 0, 0)) != 0)
    {   LM_ERR("Error while getting column names\n");
        goto error;
    }

    db = _tp->db;
    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, klen);
    memset(&data, 0, sizeof(DBT));
    memset(dbuf, 0, MAX_ROW_SIZE);

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;

    /* Acquire a cursor for the database. */
    if ((ret = db->cursor(db, NULL, &dbcp, DB_WRITECURSOR)) != 0)
    {   LM_ERR("Error creating cursor\n");
    }

    while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
    {
        if(!strncasecmp((char*)key.data,"METADATA",8))
            continue;

        /*fill in the row part of db_res_t */
        if ((ret=bdb_convert_row( _r, dbuf, 0)) < 0)
        {   LM_ERR("Error while converting row\n");
            goto error;
        }

        if(bdb_row_match(_k, _op, _v, _n, _r, lkey ))
        {

#ifdef BDB_EXTRA_DEBUG
            LM_DBG("DELETE ROW by KEY:  [%.*s]\n", (int) key.size,
                   (char *)key.data);
#endif

            if((ret = dbcp->c_del(dbcp, 0)) != 0)
            {
                /* Berkeley DB error handler */
                LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
                bdblib_recover(_tp,ret);
            }

        }

        memset(dbuf, 0, MAX_ROW_SIZE);
        bdb_free_rows( _r);
    }
    ret = 0;

error:
    if(dbcp)
        dbcp->c_close(dbcp);
    if(_r)
        bdb_free_result(_r);
    if(lkey)
        pkg_free(lkey);

    return ret;
}
/*
 * Delete a row from table
 *
 * To delete ALL rows:
 *   do Not specify any keys, or values, and _n <=0
 *
 */
int bdb_delete(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    int i, j, ret, klen;
    int *lkey=NULL;
    DBT key;
    DB *db;
    DBC *dbcp;
    str s;

    i = j = ret = 0;
    klen=MAX_ROW_SIZE;

    if (_op)
        return ( _bdb_delete_cursor(_h, _k, _op, _v, _n) );

    if ((!_h) || !CON_TABLE(_h))
        return -1;

    s.s = (char*)CON_TABLE(_h);
    s.len = strlen(CON_TABLE(_h));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -3;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -4;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("DELETE in %.*s\n", _tp->name.len, _tp->name.s );
#endif

    db = _tp->db;
    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, klen);

    if(!_k || !_v || _n<=0)
    {
        /* Acquire a cursor for the database. */
        if ((ret = db->cursor(db, NULL, &dbcp, DB_WRITECURSOR) ) != 0)
        {   LM_ERR("Error creating cursor\n");
            goto error;
        }

        while ((ret = dbcp->c_get(dbcp, &key, NULL, DB_NEXT)) == 0)
        {
            if(!strncasecmp((char*)key.data,"METADATA",8))
                continue;
#ifdef BDB_EXTRA_DEBUG
            LM_DBG("KEY: [%.*s]\n"
                   , (int)   key.size
                   , (char *)key.data);
#endif
            ret = dbcp->c_del(dbcp, 0);
        }

        dbcp->c_close(dbcp);
        return 0;
    }

    lkey = bdb_get_colmap(_tp, _k, _n);
    if(!lkey)  return -5;

    /* make the key */
    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("Error in bdblib_makekey\n");
        ret = -6;
        goto error;
    }

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = klen;

    if ((ret = db->del(db, NULL, &key, 0)) == 0)
    {
        bdblib_log(JLOG_DELETE, _tp, kbuf, klen);

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("DELETED ROW \n KEY: %s \n", (char *)key.data);
#endif
    }
    else
    {   /*Berkeley DB error handler*/
        switch(ret) {

        case DB_NOTFOUND:
            ret = 0;
            break;

        /*The following are all critical/fatal */
        case DB_LOCK_DEADLOCK:
        /* The operation was selected to resolve a deadlock. */
        case DB_SECONDARY_BAD:
        /* A secondary index references a nonexistent primary key. */
        case DB_RUNRECOVERY:
        default:
            LM_CRIT("DB->del error: %s.\n"
                    , db_strerror(ret));
            bdblib_recover(_tp, ret);
            goto error;
        }
    }

    ret = 0;

error:
    if(lkey)
        pkg_free(lkey);

    return ret;

}
Beispiel #12
0
static int
bdb_tool_idl_flush_one( void *v1, void *arg )
{
	bdb_tool_idl_cache *ic = v1;
	DB *db = arg;
	struct bdb_info *bdb = bdb_tool_info;
	bdb_tool_idl_cache_entry *ice;
	DBC *curs;
	DBT key, data;
	int i, rc;
	ID id, nid;

	/* Freshly allocated, ignore it */
	if ( !ic->head && ic->count <= BDB_IDL_DB_SIZE ) {
		return 0;
	}

	rc = db->cursor( db, NULL, &curs, 0 );
	if ( rc )
		return -1;

	DBTzero( &key );
	DBTzero( &data );

	bv2DBT( &ic->kstr, &key );

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

	rc = curs->c_get( curs, &key, &data, DB_SET );
	/* If key already exists and we're writing a range... */
	if ( rc == 0 && ic->count > BDB_IDL_DB_SIZE ) {
		/* If it's not currently a range, must delete old info */
		if ( nid ) {
			/* Skip lo */
			while ( curs->c_get( curs, &key, &data, DB_NEXT_DUP ) == 0 )
				curs->c_del( curs, 0 );

			nid = 0;
			/* Store range marker */
			curs->c_put( curs, &key, &data, DB_KEYFIRST );
		} else {
			
			/* Skip lo */
			rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP );

			/* Get hi */
			rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP );

			/* Delete hi */
			curs->c_del( curs, 0 );
		}
		BDB_ID2DISK( ic->last, &nid );
		curs->c_put( curs, &key, &data, DB_KEYLAST );
		rc = 0;
	} else if ( rc && rc != DB_NOTFOUND ) {
		rc = -1;
	} else if ( ic->count > BDB_IDL_DB_SIZE ) {
		/* range, didn't exist before */
		nid = 0;
		rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
		if ( rc == 0 ) {
			BDB_ID2DISK( ic->first, &nid );
			rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
			if ( rc == 0 ) {
				BDB_ID2DISK( ic->last, &nid );
				rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
			}
		}
		if ( rc ) {
			rc = -1;
		}
	} else {
		int n;

		/* Just a normal write */
		rc = 0;
		for ( ice = ic->head, n=0; ice; ice = ice->next, n++ ) {
			int end;
			if ( ice->next ) {
				end = IDBLOCK;
			} else {
				end = ic->count & (IDBLOCK-1);
				if ( !end )
					end = IDBLOCK;
			}
			for ( i=0; i<end; i++ ) {
				if ( !ice->ids[i] ) continue;
				BDB_ID2DISK( ice->ids[i], &nid );
				rc = curs->c_put( curs, &key, &data, DB_NODUPDATA );
				if ( rc ) {
					if ( rc == DB_KEYEXIST ) {
						rc = 0;
						continue;
					}
					rc = -1;
					break;
				}
			}
			if ( rc ) {
				rc = -1;
				break;
			}
		}
		if ( ic->head ) {
			ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
			ic->tail->next = bdb_tool_idl_free_list;
			bdb_tool_idl_free_list = ic->head;
			bdb->bi_idl_cache_size -= n;
			ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
		}
	}
	if ( ic != db->app_private ) {
		ch_free( ic );
	} else {
		ic->head = ic->tail = NULL;
	}
	curs->c_close( curs );
	return rc;
}
Beispiel #13
0
static void
run_expiry()
{
    DB_ENV *dbenv;
    DB *db;
    DB_TXN *txn;
    DBC *dbcp;
    int rc;
    time_t now;
    DBT key = { 0 };
    unsigned int count = 0;
    if (exit_requested)
	return;
    /* Cursor operations can hold several locks and therefore deadlock
       so don't run expiry if deadlock detection does not work
       http://docs.oracle.com/cd/E17076_02/html/programmer_reference/lock_notxn.html */
    rc = get_db(&db, 0);
    assert(! rc);
    if (db == 0 || deadlock_detect == 0)
	return;
    rc = get_dbenv(&dbenv, 0);
    assert(! rc && dbenv);
    if (time(&now) == (time_t)-1) {
	syslog(LOG_ERR, "time failed during run_expiry");
	return;
    }
    muffle_error++;
    rc = dbenv->txn_begin(dbenv, NULL, &txn, DB_TXN_NOWAIT);
    if (rc) {
	if (rc == DB_LOCK_DEADLOCK)
	    syslog(LOG_DEBUG, "skipping concurrent expiry avoids "
		   "deadlocks and unnecessary work");
	else
	    log_db_error("txn_begin failed during run_expiry", rc);
	goto out;
    }
#if DB_VERSION_MAJOR >= 5
    call_db(txn->set_priority(txn, 50), "TXN->set_priority");
#endif
    rc = call_db(db->cursor(db, txn, &dbcp, 0),
		 "db->cursor failed during expiry run");
    if (rc)
	goto txn_fail;
    while ((rc = dbcp->c_get(dbcp, &key, &dbdata, DB_NEXT | DB_RMW)) == 0) {
	time_t ref_time;
	double age_max, age;
	if (triplet_data.pass_count) {
	    ref_time = triplet_data.access_time;
	    age_max = pass_max_idle;
	}
	else {
	    ref_time = triplet_data.create_time;
	    age_max = bloc_max_idle;
	}
	age = difftime(now, ref_time);
	if (age > age_max) {
	    if (opt_verbose) {
		syslog(LOG_INFO, "Expiring %s %s after %.0f seconds idle",
		       db_key_ntop(key.data),
		       triplet_data.pass_count ? "pass" : "block", age);
	    }
	    rc = call_db(dbcp->c_del(dbcp, 0), "dbcp->c_del failed");
	    if (rc)
		goto cursor_fail;
	    count++;
	}
	if (exit_requested)
	    break;
    }
    if (rc && rc != DB_NOTFOUND) {
	if (rc == DB_LOCK_DEADLOCK)
	    syslog(LOG_NOTICE, "Aborting concurrent expiry due to deadlock");
	else
	    log_db_error("dbcp->c_get failed", rc);
	goto cursor_fail;
    }
    if (call_db(dbcp->c_close(dbcp), "dbcp->c_close failed"))
	goto txn_fail;
    call_db(txn->commit(txn, 0), "commit failed in run_expiry");
    if (count)
	syslog(LOG_NOTICE, "Expired %u triplets", count);
    goto out;

  cursor_fail:
    call_db(dbcp->c_close(dbcp), "dbcp->c_close failed");
  txn_fail:
    call_db(txn->abort(txn), "failed to abort");
  out:
    muffle_error--;
    return;
}
Beispiel #14
0
icalerrorenum icalbdbset_commit(icalset *set)
{
    DB *dbp;
    DBC *dbcp;
    DBT key, data;
    icalcomponent *c;
    char *str = NULL;
    int ret = 0;
    int reterr = ICAL_NO_ERROR;
    char keystore[256];
    char uidbuf[256];
    char datastore[1024];
    char *more_mem = NULL;
    DB_TXN *tid = NULL;
    icalbdbset *bset = (icalbdbset *) set;
    int bad_uid_counter = 0;
    int retry = 0, done = 0, completed = 0, deadlocked = 0;

    icalerror_check_arg_re((bset != 0), "bset", ICAL_BADARG_ERROR);

    dbp = bset->dbp;
    icalerror_check_arg_re((dbp != 0), "dbp is invalid", ICAL_BADARG_ERROR);

    if (bset->changed == 0) {
        return ICAL_NO_ERROR;
    }

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

    key.flags = DB_DBT_USERMEM;
    key.data = keystore;
    key.ulen = (u_int32_t) sizeof(keystore);

    data.flags = DB_DBT_USERMEM;
    data.data = datastore;
    data.ulen = (u_int32_t) sizeof(datastore);

    if (!ICAL_DB_ENV) {
        if (icalbdbset_init_dbenv(NULL, NULL) != 0) {
            return ICAL_INTERNAL_ERROR;
        }
    }

    while ((retry < MAX_RETRY) && !done) {

        if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) {
            if (ret == DB_LOCK_DEADLOCK) {
                retry++;
                continue;
            } else if (ret == DB_RUNRECOVERY) {
                ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "icalbdbset_commit: txn_begin failed");
                abort();
            } else {
                ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "icalbdbset_commit");
                return ICAL_INTERNAL_ERROR;
            }
        }

        /* first delete everything in the database, because there could be removed components */
        if ((ret = dbp->cursor(dbp, tid, &dbcp, DB_DIRTY_READ)) != 0) {
            tid->abort(tid);
            if (ret == DB_LOCK_DEADLOCK) {
                retry++;
                continue;
            } else if (ret == DB_RUNRECOVERY) {
                ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "curor failed");
                abort();
            } else {
                ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "curor failed");
                /* leave bset->changed set to true */
                return ICAL_INTERNAL_ERROR;
            }
        }

        /* fetch the key/data pair, then delete it */
        completed = 0;
        while (!completed && !deadlocked) {
            ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT);
            if (ret == DB_NOTFOUND) {
                completed = 1;
            } else if (ret == ENOMEM) {
                if (more_mem) {
                    free(more_mem);
                }
                more_mem = malloc(data.ulen + 1024);
                data.data = more_mem;
                data.ulen = data.ulen + 1024;
            } else if (ret == DB_LOCK_DEADLOCK) {
                deadlocked = 1;
            } else if (ret == DB_RUNRECOVERY) {
                tid->abort(tid);
                ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_get failed.");
                abort();
            } else if (ret == 0) {
                if ((ret = dbcp->c_del(dbcp, 0)) != 0) {
                    dbp->err(dbp, ret, "cursor");
                    if (ret == DB_KEYEMPTY) {
                        /* never actually created, continue onward.. */
                        /* do nothing - break; */
                    } else if (ret == DB_LOCK_DEADLOCK) {
                        deadlocked = 1;
                    } else {
                        /*char *foo = db_strerror(ret); */
                        abort();
                    }
                }
            } else {    /* some other non-fatal error */
                dbcp->c_close(dbcp);
                tid->abort(tid);
                if (more_mem) {
                    free(more_mem);
                    more_mem = NULL;
                }
                return ICAL_INTERNAL_ERROR;
            }
        }

        if (more_mem) {
            free(more_mem);
            more_mem = NULL;
        }

        if (deadlocked) {
            dbcp->c_close(dbcp);
            tid->abort(tid);
            retry++;
            continue;   /* next retry */
        }

        deadlocked = 0;
        for (c = icalcomponent_get_first_component(bset->cluster, ICAL_ANY_COMPONENT);
             c != 0 && !deadlocked;
             c = icalcomponent_get_next_component(bset->cluster, ICAL_ANY_COMPONENT)) {

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

            /* Note that we're always inserting into a primary index. */
            if (icalcomponent_isa(c) != ICAL_VAGENDA_COMPONENT) {
                char *uidstr = (char *)icalcomponent_get_uid(c);

                if (!uidstr) {  /* this shouldn't happen */
                    /* no uid string, we need to add one */
                    snprintf(uidbuf, 256, "baduid%d-%d", getpid(), bad_uid_counter++);
                    key.data = uidbuf;
                } else {
                    key.data = uidstr;
                }
            } else {
                char *relcalid = NULL;

                relcalid = (char *)icalcomponent_get_relcalid(c);
                if (relcalid == NULL) {
                    snprintf(uidbuf, 256, "baduid%d-%d", getpid(), bad_uid_counter++);
                    key.data = uidbuf;
                } else {
                    key.data = relcalid;
                }
            }
            key.size = (u_int32_t) strlen(key.data);

            str = icalcomponent_as_ical_string_r(c);
            data.data = str;
            data.size = (u_int32_t) strlen(str);

            if ((ret = dbcp->c_put(dbcp, &key, &data, DB_KEYLAST)) != 0) {
                if (ret == DB_LOCK_DEADLOCK) {
                    deadlocked = 1;
                } else if (ret == DB_RUNRECOVERY) {
                    ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_put failed.");
                    abort();
                } else {
                    ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_put failed %s.", str);
                    /* continue to try to put as many icalcomponent as possible */
                    reterr = ICAL_INTERNAL_ERROR;
                }
            }
        }

        if (str) {
            free(str);
        }

        if (deadlocked) {
            dbcp->c_close(dbcp);
            tid->abort(tid);
            retry++;
            continue;
        }

        if ((ret = dbcp->c_close(dbcp)) != 0) {
            tid->abort(tid);
            if (ret == DB_LOCK_DEADLOCK) {
                retry++;
                continue;
            } else if (ret == DB_RUNRECOVERY) {
                ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_closed failed.");
                abort();
            } else {
                ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_closed failed.");
                reterr = ICAL_INTERNAL_ERROR;
            }
        }

        if ((ret = tid->commit(tid, 0)) != 0) {
            tid->abort(tid);
            if (ret == DB_LOCK_DEADLOCK) {
                retry++;
                continue;
            } else if (ret == DB_RUNRECOVERY) {
                ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "commit failed.");
                abort();
            } else {
                ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "commit failed.");
                reterr = ICAL_INTERNAL_ERROR;
            }
        }

        done = 1;
    }

    bset->changed = 0;
    return reterr;
}
Beispiel #15
0
Datei: idl.c Projekt: 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;
}
Beispiel #16
0
int
b_del(int argc, char *argv[])
{
	extern char *optarg;
	extern int optind, __db_getopt_reset;
	DB *dbp;
	DBC *dbc;
	DBT key, data;
	DBTYPE type;
#if DB_VERSION_MAJOR > 5 || (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR >= 2)
	DB_HEAP_RID rid;
#endif
	db_recno_t recno;
	u_int32_t cachesize;
	int ch, i, count, ret, use_cursor;
	char *ts, buf[32];

	type = DB_BTREE;
	cachesize = MEGABYTE;
	count = 100000;
	use_cursor = 0;
	ts = "Btree";
	__db_getopt_reset = 1;
	while ((ch = getopt(argc, argv, "C:c:t:w")) != EOF)
		switch (ch) {
		case 'C':
			cachesize = (u_int32_t)atoi(optarg);
			break;
		case 'c':
			count = atoi(optarg);
			break;
		case 't':
			switch (optarg[0]) {
			case 'B': case 'b':
				ts = "Btree";
				type = DB_BTREE;
				break;
			case 'H': case 'h':
				if (optarg[1] == 'E' || optarg[1] == 'e') {
#if DB_VERSION_MAJOR > 5 || (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR >= 2)
					if (b_util_have_heap())
						return (0);
					ts = "Heap";
					type = DB_HEAP;
#else
					fprintf(stderr,
				"b_curwalk: Heap is not supported! \n");
					return (EXIT_SUCCESS);
#endif
				} else {
					if (b_util_have_hash())
						return (0);
					ts = "Hash";
					type = DB_HASH;
				}
				break;
			case 'Q': case 'q':
				if (b_util_have_queue())
					return (0);
				ts = "Queue";
				type = DB_QUEUE;
				break;
			case 'R': case 'r':
				ts = "Recno";
				type = DB_RECNO;
				break;
			default:
				return (b_del_usage());
			}
			break;
		case 'w':
			use_cursor = 1;
			break;
		case '?':
		default:
			return (b_del_usage());
		}
	argc -= optind;
	argv += optind;
	if (argc != 0)
		return (b_del_usage());

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

#if DB_VERSION_MAJOR > 5 || (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR >= 2)
	/* Need a cursor if using Heap. */
	if (type == DB_HEAP && !use_cursor) {
		printf("Heap databases require the -w flag.\n");
		return (-1);
	}
#endif

	/* Set record length for Queue. */
	if (type == DB_QUEUE)
		DB_BENCH_ASSERT(dbp->set_re_len(dbp, 20) == 0);

#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
	DB_BENCH_ASSERT(
	    dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
	DB_BENCH_ASSERT(
	    dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif

	/* Initialize the data. */
	memset(&key, 0, sizeof(key));
	memset(&data, 0, sizeof(data));
	data.data = "01234567890123456789";
	data.size = 20;

	/* Store a key/data pair. */
	switch (type) {
	case DB_BTREE:
	case DB_HASH:
		key.data = buf;
		key.size = 10;
		break;
#if DB_VERSION_MAJOR > 5 || (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR >= 2)
	case DB_HEAP:
		key.data = &rid;
		key.size = sizeof(rid);
		break;
#endif
	case DB_QUEUE:
	case DB_RECNO:
		key.data = &recno;
		key.size = sizeof(recno);
		break;
	case DB_UNKNOWN:
		b_util_abort();
		break;
	}

	/* Insert count in-order key/data pairs. */
	if (type == DB_BTREE || type == DB_HASH)
		for (i = 0; i < count; ++i) {
			(void)snprintf(buf, sizeof(buf), "%010d", i);
			DB_BENCH_ASSERT(
			    dbp->put(dbp, NULL, &key, &data, 0) == 0);
		}
#if DB_VERSION_MAJOR > 5 || (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR >= 2)
	else if (type == DB_HEAP)
		for (i = 0; i < count; i++)
			DB_BENCH_ASSERT(
			    dbp->put(dbp, NULL, &key, &data, DB_APPEND) == 0);
#endif
	else
		for (i = 0, recno = 1; i < count; ++i, ++recno)
			DB_BENCH_ASSERT(
			    dbp->put(dbp, NULL, &key, &data, 0) == 0);

	/* Delete the records. */
	TIMER_START;
	if (use_cursor) {
		DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
		while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0)
			DB_BENCH_ASSERT(dbc->c_del(dbc, 0) == 0);
		DB_BENCH_ASSERT (ret == DB_NOTFOUND);
	} else
		if (type == DB_BTREE || type == DB_HASH)
			for (i = 0; i < count; ++i) {
				(void)snprintf(buf, sizeof(buf), "%010d", i);
				DB_BENCH_ASSERT(
				    dbp->del(dbp, NULL, &key, 0) == 0);
			}
		else
			for (i = 0, recno = 1; i < count; ++i, ++recno)
				DB_BENCH_ASSERT(
				    dbp->del(dbp, NULL, &key, 0) == 0);

	TIMER_STOP;

	printf(
    "# %d %s database in-order delete of 10/20 byte key/data pairs using %s\n",
	    count, ts, use_cursor ? "a cursor" : "the key");
	TIMER_DISPLAY(count);

	DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);

	return (0);
}
Beispiel #17
0
/**
 * librdf_hash_bdb_delete_key_value - Delete given key/value from the hash
 * @context: BerkeleyDB hash context
 * @key: key
 * @value: value
 * 
 * Return value: non 0 on failure
 **/
static int
librdf_hash_bdb_delete_key_value(void* context, 
                                 librdf_hash_datum *key, librdf_hash_datum *value)
{
  librdf_hash_bdb_context* bdb_context=(librdf_hash_bdb_context*)context;
  DB* bdb=bdb_context->db;
  DBT bdb_key, bdb_value;
  int ret;
#ifdef HAVE_BDB_CURSOR
  DBC* dbc;
#endif

  memset(&bdb_key, 0, sizeof(DBT));
  memset(&bdb_value, 0, sizeof(DBT));

  /* Initialise BDB version of key */
  bdb_key.data = (char*)key->data;
  bdb_key.size = key->size;
  
  bdb_value.data = (char*)value->data;
  bdb_value.size = value->size;
  
#ifdef HAVE_BDB_CURSOR
#ifdef HAVE_BDB_CURSOR_4_ARGS
  /* V3 prototype:
   * int DB->cursor(DB *db, DB_TXN *txnid, DBC **cursorp, u_int32_t flags);
   */
  if(bdb->cursor(bdb, NULL, &dbc, 0))
    return 1;
#else
  /* V2 prototype:
   * int DB->cursor(DB *db, DB_TXN *txnid, DBC **cursorp);
   */
  if(bdb->cursor(bdb, NULL, &dbc))
    return 1;
#endif
  
  /* V2/V3 prototype:
   * int DBcursor->c_get(DBC *cursor, DBT *key, DBT *data, u_int32_t flags);
   */
#ifdef DB_GET_BOTH
  /* later V2 (sigh) / V3 */
  ret=dbc->c_get(dbc, &bdb_key, &bdb_value, DB_GET_BOTH);
#else
  /* earlier V2 probably gives a memory leak */
  ret=dbc->c_get(dbc, &bdb_key, &bdb_value, 0);
#endif
  if(ret) {
    dbc->c_close(dbc);
    return 1;
  }
  
  /* finally - delete the sucker */
  ret=dbc->c_del(dbc, 0);

  dbc->c_close(dbc);
#else
  /* V1 prototype:
   * int db->seq(DB* db, DBT *key, DBT *data, u_int flags);
   */
  ret=bdb->seq(bdb, &bdb_key, &bdb_value, 0);
  if(ret)
    return 1;
  
  /* V1 prototype:
   * int db->del(DB* db, DBT *key, u_int flags);
   */
  ret=bdb->del(bdb, &bdb_key, R_CURSOR);
#endif

  if(ret)
    LIBRDF_DEBUG2("BDB del failed - %d\n", ret);

  return (ret != 0);
}
Beispiel #18
0
int
hdb_dn2id_delete(
	Operation	*op,
	DB_TXN *txn,
	EntryInfo	*eip,
	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;
	diskNode *d;
	int rc;
	ID	nid;
	unsigned char dlen[2];

	Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id_delete 0x%lx: \"%s\"\n",
		e->e_id, e->e_ndn, 0 );

	DBTzero(&key);
	key.size = sizeof(ID);
	key.ulen = key.size;
	key.flags = DB_DBT_USERMEM;
	BDB_ID2DISK( eip->bei_id, &nid );

	DBTzero(&data);
	data.size = sizeof(diskNode) + BEI(e)->bei_nrdn.bv_len - sizeof(ID) - 1;
	data.ulen = data.size;
	data.dlen = data.size;
	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;

	key.data = &nid;

	d = op->o_tmpalloc( data.size, op->o_tmpmemctx );
	d->nrdnlen[1] = BEI(e)->bei_nrdn.bv_len & 0xff;
	d->nrdnlen[0] = (BEI(e)->bei_nrdn.bv_len >> 8) | 0x80;
	dlen[0] = d->nrdnlen[0];
	dlen[1] = d->nrdnlen[1];
	memcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val, BEI(e)->bei_nrdn.bv_len+1 );
	data.data = d;

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

	/* Delete our ID from the parent's list */
	rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE );
	if ( rc == 0 ) {
		if ( dlen[1] == d->nrdnlen[1] && dlen[0] == d->nrdnlen[0] &&
			!strcmp( d->nrdn, BEI(e)->bei_nrdn.bv_val ))
			rc = cursor->c_del( cursor, 0 );
		else
			rc = DB_NOTFOUND;
	}

	/* Delete our ID from the tree. With sorted duplicates, this
	 * will leave any child nodes still hanging around. This is OK
	 * for modrdn, which will add our info back in later.
	 */
	if ( rc == 0 ) {
		BDB_ID2DISK( e->e_id, &nid );
		rc = cursor->c_get( cursor, &key, &data, DB_SET );
		if ( rc == 0 )
			rc = cursor->c_del( cursor, 0 );
	}

	cursor->c_close( cursor );
func_leave:
	op->o_tmpfree( d, op->o_tmpmemctx );

	/* Delete IDL cache entries */
	if ( rc == 0 && bdb->bi_idl_cache_size ) {
		ID tmp[2];
		char *ptr = ((char *)&tmp[1])-1;
		key.data = ptr;
		key.size = sizeof(ID)+1;
		tmp[1] = eip->bei_id;
		*ptr = DN_ONE_PREFIX;
		bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
		if ( eip ->bei_parent ) {
			*ptr = DN_SUBTREE_PREFIX;
			for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
				tmp[1] = eip->bei_id;
				bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
			}
			/* Handle DB with empty suffix */
			if ( !op->o_bd->be_suffix[0].bv_len && eip ) {
				tmp[1] = eip->bei_id;
				bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
			}
		}
	}
	Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id_delete 0x%lx: %d\n", e->e_id, rc, 0 );
	return rc;
}
Beispiel #19
0
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, tmp;
	char *err;

	{
		char buf[16];
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ARGS,
			"bdb_idl_insert_key: %lx %s\n", 
			(long) id, bdb_show_key( key, buf ), 0 );
#else
		Debug( LDAP_DEBUG_ARGS,
			"bdb_idl_insert_key: %lx %s\n", 
			(long) id, bdb_show_key( key, buf ), 0 );
#endif
	}

	assert( id != NOID );

#ifdef SLAP_IDL_CACHE
	if ( bdb->bi_idl_cache_size ) {
		bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp;
		DBT2bv( key, &idl_tmp.kstr );
		idl_tmp.db = db;
		ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_mutex );
		matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
		                              bdb_idl_entry_cmp );
		if ( matched_idl_entry != NULL ) {
			if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry,
				            bdb_idl_entry_cmp ) == NULL ) {
#ifdef NEW_LOGGING
				LDAP_LOG( INDEX, ERR, 
					"bdb_idl_fetch_key: AVL delete failed\n", 
					0, 0, 0 );
#else
				Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
					"AVL delete failed\n",
					0, 0, 0 );
#endif
			}
			--bdb->bi_idl_cache_size;
			IDL_LRU_DELETE( bdb, matched_idl_entry );
			free( matched_idl_entry->kstr.bv_val );
			free( matched_idl_entry->idl );
			free( matched_idl_entry );
		}
		ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_mutex );
	}
#endif

	DBTzero( &data );
	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 ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, 
			"bdb_idl_insert_key: cursor failed: %s (%d)\n", 
			db_strerror(rc), rc, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
			"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
#endif
		return rc;
	}
	data.data = &tmp;
	/* 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 | DB_RMW );
	err = "c_get";
	if ( rc == 0 ) {
		if ( tmp != 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;

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

				lo = tmp;
				data.data = &hi;
				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;
					}
				}
				if ( id < lo )
					lo = id;
				else if ( id > hi )
					hi = id;
				rc = db->del( db, tid, key, 0 );
				if ( rc != 0 ) {
					err = "del";
					goto fail;
				}
				data.data = &id;
				id = 0;
				rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
				if ( rc != 0 ) {
					err = "c_put 0";
					goto fail;
				}
				id = lo;
				rc = cursor->c_put( cursor, key, &data, DB_KEYLAST );
				if ( rc != 0 ) {
					err = "c_put lo";
					goto fail;
				}
				id = hi;
				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 = &lo;
			rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
			if ( rc != 0 ) {
				err = "c_get lo";
				goto fail;
			}
			if ( id > lo ) {
				data.data = &hi;
				rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
				if ( rc != 0 ) {
					err = "c_get hi";
					goto fail;
				}
			}
			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 = &id;
				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 = &id;
		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:
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, 
			"bdb_idl_insert_key: %s failed: %s (%d)\n", 
			err, db_strerror(rc), rc );
#else
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
			"%s failed: %s (%d)\n", err, db_strerror(rc), rc );
#endif
		cursor->c_close( cursor );
		return rc;
	}
	rc = cursor->c_close( cursor );
	if( rc != 0 ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, 
			"bdb_idl_insert_key: c_close failed: %s (%d)\n", 
			db_strerror(rc), rc, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
			"c_close failed: %s (%d)\n",
			db_strerror(rc), rc, 0 );
#endif
	}
	return rc;
}
Beispiel #20
0
Datei: idl.c Projekt: 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;
}
Beispiel #21
0
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;
	char *err;

	{
		char buf[16];
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ARGS,
			"bdb_idl_delete_key: %lx %s\n", 
			(long) id, bdb_show_key( key, buf ), 0 );
#else
		Debug( LDAP_DEBUG_ARGS,
			"bdb_idl_delete_key: %lx %s\n", 
			(long) id, bdb_show_key( key, buf ), 0 );
#endif
	}
	assert( id != NOID );

#ifdef SLAP_IDL_CACHE
	if ( bdb->bi_idl_cache_max_size ) {
		bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp;
		DBT2bv( key, &idl_tmp.kstr );
		idl_tmp.db = db;
		ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_mutex );
		matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
		                              bdb_idl_entry_cmp );
		if ( matched_idl_entry != NULL ) {
			if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry,
				            bdb_idl_entry_cmp ) == NULL ) {
#ifdef NEW_LOGGING
				LDAP_LOG( INDEX, ERR, 
					"bdb_idl_fetch_key: AVL delete failed\n", 
					0, 0, 0 );
#else
				Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
					"AVL delete failed\n",
					0, 0, 0 );
#endif
			}
			--bdb->bi_idl_cache_size;
			IDL_LRU_DELETE( bdb, matched_idl_entry );
			free( matched_idl_entry->kstr.bv_val );
			free( matched_idl_entry->idl );
			free( matched_idl_entry );
		}
		ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_mutex );
	}
#endif

	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 ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, 
			"bdb_idl_delete_key: cursor failed: %s (%d)\n", 
			db_strerror(rc), rc, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
			"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
#endif
		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 | DB_RMW );
	err = "c_get";
	if ( rc == 0 ) {
		if ( tmp != 0 ) {
			/* Not a range, just delete it */
			if (tmp != id) {
				/* position to correct item */
				tmp = id;
				rc = cursor->c_get( cursor, key, &data, 
					DB_GET_BOTH | DB_RMW  );
				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 = &lo;
			rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
			if ( rc != 0 ) {
				err = "c_get lo";
				goto fail;
			}
			data.data = &hi;
			rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
			if ( rc != 0 ) {
				err = "c_get hi";
				goto fail;
			}
			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 = &lo;
						cursor->c_get( cursor, key, &data, DB_PREV );
						lo = id;
					}
					rc = cursor->c_del( cursor, 0 );
					if ( rc != 0 ) {
						err = "c_del";
						goto fail;
					}
				}
				if ( lo <= hi ) {
					data.data = &id;
					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 ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, 
			"bdb_idl_delete_key: %s failed: %s (%d)\n", 
			err, db_strerror(rc), rc );
#else
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
			"%s failed: %s (%d)\n", err, db_strerror(rc), rc );
#endif
		}
		cursor->c_close( cursor );
		return rc;
	}
	rc = cursor->c_close( cursor );
	if( rc != 0 ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, "bdb_idl_delete_key: c_close failed: %s (%d)\n", 
			db_strerror(rc), rc, 0 );
#else
		Debug( LDAP_DEBUG_ANY,
			"=> bdb_idl_delete_key: c_close failed: %s (%d)\n",
			db_strerror(rc), rc, 0 );
#endif
	}

	return rc;
}