+ } else if ( data.size != BDB_IDL_SIZEOF(ids) ) {
+ /* size mismatch */
+#ifdef NEW_LOGGING
+ LDAP_LOG( INDEX, ERR,
+ "bdb_idl_insert_key: odd size: expected %ld multiple, got %ld\n",
+ (long) ((1 + ids[0]) * sizeof( ID )), (long) data.size, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
+ "get size mismatch: expected %ld, got %ld\n",
+ (long) ((1 + ids[0]) * sizeof( ID )), (long) data.size, 0 );
+#endif
+ return -1;
+
+ } else if ( BDB_IDL_IS_RANGE(ids) ) {
+ if( id < ids[1] ) {
+ ids[1] = id;
+ } else if ( ids[2] > id ) {
+ ids[2] = id;
+ } else {
+ return 0;
+ }
+
+ } else {
+ rc = bdb_idl_insert( ids, id );
+
+ if( rc == -1 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( INDEX, DETAIL1, "bdb_idl_insert_key: dup\n", 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "=> bdb_idl_insert_key: dup\n",
+ 0, 0, 0 );
+#endif
+ return 0;
+ }
+ if( rc != 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( INDEX, ERR,
+ "bdb_idl_insert_key: insert failed: (%d)\n", rc, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
+ "bdb_idl_insert failed (%d)\n",
+ rc, 0, 0 );
+#endif
+
+ return rc;
+ }
+
+ data.size = BDB_IDL_SIZEOF( ids );
+ }
+
+ /* store the key */
+ rc = db->put( db, tid, key, &data, 0 );
+#endif
+ if( rc == DB_KEYEXIST ) rc = 0;
+
+ if( rc != 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( INDEX, ERR,
+ "bdb_idl_insert_key: put failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
+ "put failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+#endif
+ }
+ return rc;
+}
+
+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;
+#ifndef BDB_IDL_MULTI
+ ID ids[BDB_IDL_DB_SIZE];
+#endif
+
+#if 0
+ /* for printable keys only */
+#ifdef NEW_LOGGING
+ LDAP_LOG( INDEX, ARGS, "bdb_idl_delete_key: %s %ld\n",
+ (char *)key->data, (long) id, 0 );
+#else
+ Debug( LDAP_DEBUG_ARGS,
+ "=> bdb_idl_delete_key: %s %ld\n",
+ (char *)key->data, (long) id, 0 );
+#endif
+#endif
+
+ assert( id != NOID );
+
+ DBTzero( &data );
+#ifdef BDB_IDL_MULTI
+ {
+ DBC *cursor;
+ ID lo, hi, tmp;
+ char *err;
+
+ 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 ) {
+ 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
+ */
+ hi = 0;
+ 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 ) {
+ 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 {
+ 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:
+#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 );
+ }
+#else
+ data.data = ids;
+ data.ulen = sizeof( ids );
+ data.flags = DB_DBT_USERMEM;
+
+ /* fetch the key for read/modify/write */
+ rc = db->get( db, tid, key, &data, DB_RMW | bdb->bi_db_opflags );
+
+ if ( rc != 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( INDEX, ERR, "bdb_idl_delete_key: get failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
+ "get failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+#endif
+ return rc;
+
+ } else if ( data.size == 0 || data.size % sizeof( ID ) ) {
+ /* size not multiple of ID size */
+#ifdef NEW_LOGGING
+ LDAP_LOG( INDEX, ERR,
+ "bdb_idl_delete_key: odd size: expected: %ld multiple, got %ld\n",
+ (long) sizeof( ID ), (long) data.size, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
+ "odd size: expected %ld multiple, got %ld\n",
+ (long) sizeof( ID ), (long) data.size, 0 );
+#endif
+ return -1;
+
+ } else if ( BDB_IDL_IS_RANGE(ids) ) {