mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-06 10:46:21 +08:00
Byte-order independence for HDB: dn2id format changed again.
This commit is contained in:
parent
bd498d2996
commit
89da582d69
@ -261,19 +261,19 @@ struct bdb_op_info {
|
|||||||
|
|
||||||
/* Copy an ID "src" to pointer "dst" in big-endian byte order */
|
/* Copy an ID "src" to pointer "dst" in big-endian byte order */
|
||||||
#define BDB_ID2DISK( src, dst ) \
|
#define BDB_ID2DISK( src, dst ) \
|
||||||
do { int i0; ID tmp; char *ptr; \
|
do { int i0; ID tmp; unsigned char *_p; \
|
||||||
tmp = (src); ptr = (char *)(dst); \
|
tmp = (src); _p = (char *)(dst); \
|
||||||
for ( i0=sizeof(ID)-1; i0>=0; i0-- ) { \
|
for ( i0=sizeof(ID)-1; i0>=0; i0-- ) { \
|
||||||
ptr[i0] = tmp & 0xff; tmp >>= 8; \
|
_p[i0] = tmp & 0xff; tmp >>= 8; \
|
||||||
} \
|
} \
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
/* Copy a pointer "src" to a pointer "dst" from big-endian to native order */
|
/* Copy a pointer "src" to a pointer "dst" from big-endian to native order */
|
||||||
#define BDB_DISK2ID( src, dst ) \
|
#define BDB_DISK2ID( src, dst ) \
|
||||||
do { int i0; ID tmp = 0; unsigned char *ptr; \
|
do { int i0; ID tmp = 0; unsigned char *_p; \
|
||||||
ptr = (unsigned char *)(src); \
|
_p = (unsigned char *)(src); \
|
||||||
for ( i0=0; i0<sizeof(ID); i0++ ) { \
|
for ( i0=0; i0<sizeof(ID); i0++ ) { \
|
||||||
tmp <<= 8; tmp |= *ptr++; \
|
tmp <<= 8; tmp |= *_p++; \
|
||||||
} *(dst) = tmp; \
|
} *(dst) = tmp; \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
@ -391,45 +391,21 @@ bdb_dn2idl(
|
|||||||
* a B-Tree with sorted duplicates to store all the children of a node under
|
* a B-Tree with sorted duplicates to store all the children of a node under
|
||||||
* the same key. Also, the first item under the key contains the entry's own
|
* the same key. Also, the first item under the key contains the entry's own
|
||||||
* rdn and the ID of the node's parent, to allow bottom-up tree traversal as
|
* rdn and the ID of the node's parent, to allow bottom-up tree traversal as
|
||||||
* well as top-down. To keep this info first in the list, the nrdnlen is set
|
* well as top-down. To keep this info first in the list, the high bit of all
|
||||||
* to the negative of its value.
|
* subsequent nrdnlen's is always set. This means we can only accomodate
|
||||||
|
* RDNs up to length 32767, but that's fine since full DNs are already
|
||||||
|
* restricted to 8192.
|
||||||
*
|
*
|
||||||
* The diskNode is a variable length structure. This definition is not
|
* The diskNode is a variable length structure. This definition is not
|
||||||
* directly usable for in-memory manipulation.
|
* directly usable for in-memory manipulation.
|
||||||
*/
|
*/
|
||||||
typedef struct diskNode {
|
typedef struct diskNode {
|
||||||
ID entryID;
|
unsigned char nrdnlen[2];
|
||||||
short nrdnlen;
|
unsigned char nrdn[1];
|
||||||
char nrdn[1];
|
unsigned char rdn[1];
|
||||||
char rdn[1];
|
unsigned char entryID[sizeof(ID)];
|
||||||
} diskNode;
|
} diskNode;
|
||||||
|
|
||||||
/* Sort function for the sorted duplicate data items of a dn2id key.
|
|
||||||
* Sorts based on normalized RDN, in length order.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
hdb_dup_compare(
|
|
||||||
DB *db,
|
|
||||||
const DBT *usrkey,
|
|
||||||
const DBT *curkey )
|
|
||||||
{
|
|
||||||
signed char *u = (signed char *)&(((diskNode *)(usrkey->data))->nrdnlen);
|
|
||||||
signed char *c = (signed char *)&(((diskNode *)(curkey->data))->nrdnlen);
|
|
||||||
int rc, i;
|
|
||||||
|
|
||||||
/* data is not aligned, cannot compare directly */
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
for( i = 0; i < (int)sizeof(short); i++)
|
|
||||||
#else
|
|
||||||
for( i = sizeof(short)-1; i >= 0; i--)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
rc = u[i] - c[i];
|
|
||||||
if( rc ) return rc;
|
|
||||||
}
|
|
||||||
return strcmp( u+sizeof(short), c+sizeof(short) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function constructs a full DN for a given entry.
|
/* This function constructs a full DN for a given entry.
|
||||||
*/
|
*/
|
||||||
int hdb_fix_dn(
|
int hdb_fix_dn(
|
||||||
@ -511,12 +487,13 @@ hdb_dn2id_add(
|
|||||||
}
|
}
|
||||||
|
|
||||||
d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen, op->o_tmpmemctx);
|
d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen, op->o_tmpmemctx);
|
||||||
BDB_ID2DISK( e->e_id, &d->entryID );
|
d->nrdnlen[1] = nrlen & 0xff;
|
||||||
d->nrdnlen = nrlen;
|
d->nrdnlen[0] = (nrlen >> 8) | 0x80;
|
||||||
ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen );
|
ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen );
|
||||||
*ptr++ = '\0';
|
*ptr++ = '\0';
|
||||||
ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen );
|
ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen );
|
||||||
*ptr = '\0';
|
*ptr++ = '\0';
|
||||||
|
BDB_ID2DISK( e->e_id, ptr );
|
||||||
|
|
||||||
DBTzero(&key);
|
DBTzero(&key);
|
||||||
DBTzero(&data);
|
DBTzero(&data);
|
||||||
@ -547,10 +524,9 @@ hdb_dn2id_add(
|
|||||||
rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
|
rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
ID tmp = nid;
|
BDB_ID2DISK( e->e_id, &nid );
|
||||||
nid = d->entryID;
|
BDB_ID2DISK( eip->bei_id, ptr );
|
||||||
d->entryID = tmp;
|
d->nrdnlen[0] ^= 0x80;
|
||||||
d->nrdnlen = 0 - nrlen;
|
|
||||||
|
|
||||||
rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
|
rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
|
||||||
}
|
}
|
||||||
@ -583,7 +559,7 @@ hdb_dn2id_delete(
|
|||||||
BDB_ID2DISK( eip->bei_id, &nid );
|
BDB_ID2DISK( eip->bei_id, &nid );
|
||||||
|
|
||||||
DBTzero(&data);
|
DBTzero(&data);
|
||||||
data.size = sizeof(diskNode) + BEI(e)->bei_nrdn.bv_len;
|
data.size = sizeof(diskNode) + BEI(e)->bei_nrdn.bv_len - sizeof(ID) - 1;
|
||||||
data.ulen = data.size;
|
data.ulen = data.size;
|
||||||
data.dlen = data.size;
|
data.dlen = data.size;
|
||||||
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
||||||
@ -595,15 +571,19 @@ hdb_dn2id_delete(
|
|||||||
if ( rc ) return rc;
|
if ( rc ) return rc;
|
||||||
|
|
||||||
d = op->o_tmpalloc( data.size, op->o_tmpmemctx );
|
d = op->o_tmpalloc( data.size, op->o_tmpmemctx );
|
||||||
BDB_ID2DISK( e->e_id, &d->entryID );
|
d->nrdnlen[1] = BEI(e)->bei_nrdn.bv_len & 0xff;
|
||||||
d->nrdnlen = BEI(e)->bei_nrdn.bv_len;
|
d->nrdnlen[0] = (BEI(e)->bei_nrdn.bv_len >> 8) | 0x80;
|
||||||
strcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val );
|
strcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val );
|
||||||
data.data = d;
|
data.data = d;
|
||||||
|
|
||||||
/* Delete our ID from the parent's list */
|
/* Delete our ID from the parent's list */
|
||||||
rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH | DB_RMW );
|
rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE | DB_RMW );
|
||||||
if ( rc == 0 )
|
if ( rc == 0 ) {
|
||||||
rc = cursor->c_del( cursor, 0 );
|
if ( !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
|
/* Delete our ID from the tree. With sorted duplicates, this
|
||||||
* will leave any child nodes still hanging around. This is OK
|
* will leave any child nodes still hanging around. This is OK
|
||||||
@ -649,22 +629,28 @@ hdb_dn2id(
|
|||||||
BDB_ID2DISK( ei->bei_parent->bei_id, &idp );
|
BDB_ID2DISK( ei->bei_parent->bei_id, &idp );
|
||||||
|
|
||||||
DBTzero(&data);
|
DBTzero(&data);
|
||||||
data.size = sizeof(diskNode) + nrlen;
|
data.size = sizeof(diskNode) + nrlen - sizeof(ID) - 1;
|
||||||
data.ulen = data.size * 3;
|
data.ulen = data.size * 3;
|
||||||
data.flags = DB_DBT_USERMEM;
|
data.dlen = data.ulen;
|
||||||
|
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
||||||
|
|
||||||
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
|
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
|
||||||
if ( rc ) return rc;
|
if ( rc ) return rc;
|
||||||
|
|
||||||
d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx );
|
d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx );
|
||||||
d->nrdnlen = nrlen;
|
d->nrdnlen[1] = nrlen & 0xff;
|
||||||
|
d->nrdnlen[0] = (nrlen >> 8) | 0x80;
|
||||||
ptr = lutil_strncopy( d->nrdn, in->bv_val, nrlen );
|
ptr = lutil_strncopy( d->nrdn, in->bv_val, nrlen );
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
data.data = d;
|
data.data = d;
|
||||||
|
|
||||||
rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH );
|
rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE );
|
||||||
|
if ( rc == 0 && strncmp( d->nrdn, in->bv_val, nrlen )) {
|
||||||
|
rc = DB_NOTFOUND;
|
||||||
|
}
|
||||||
if ( rc == 0 ) {
|
if ( rc == 0 ) {
|
||||||
BDB_DISK2ID( &d->entryID, &ei->bei_id );
|
ptr = data.data + data.size - sizeof(ID);
|
||||||
|
BDB_DISK2ID( ptr, &ei->bei_id );
|
||||||
ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
|
ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
|
||||||
ptr = d->nrdn + nrlen + 1;
|
ptr = d->nrdn + nrlen + 1;
|
||||||
ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );
|
ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );
|
||||||
@ -720,12 +706,13 @@ hdb_dn2id_parent(
|
|||||||
|
|
||||||
rc = cursor->c_get( cursor, &key, &data, DB_SET );
|
rc = cursor->c_get( cursor, &key, &data, DB_SET );
|
||||||
if ( rc == 0 ) {
|
if ( rc == 0 ) {
|
||||||
if (d->nrdnlen >= 0) {
|
if (d->nrdnlen[0] & 0x80) {
|
||||||
rc = LDAP_OTHER;
|
rc = LDAP_OTHER;
|
||||||
} else {
|
} else {
|
||||||
db_recno_t dkids;
|
db_recno_t dkids;
|
||||||
BDB_DISK2ID( &d->entryID, idp );
|
ptr = data.data + data.size - sizeof(ID);
|
||||||
ei->bei_nrdn.bv_len = 0 - d->nrdnlen;
|
BDB_DISK2ID( ptr, idp );
|
||||||
|
ei->bei_nrdn.bv_len = (d->nrdnlen[0] << 8) | d->nrdnlen[1];
|
||||||
ber_str2bv( d->nrdn, ei->bei_nrdn.bv_len, 1, &ei->bei_nrdn );
|
ber_str2bv( d->nrdn, ei->bei_nrdn.bv_len, 1, &ei->bei_nrdn );
|
||||||
ei->bei_rdn.bv_len = data.size - sizeof(diskNode) -
|
ei->bei_rdn.bv_len = data.size - sizeof(diskNode) -
|
||||||
ei->bei_nrdn.bv_len;
|
ei->bei_nrdn.bv_len;
|
||||||
@ -913,8 +900,8 @@ hdb_dn2idl_internal(
|
|||||||
diskNode *d = (diskNode *)j;
|
diskNode *d = (diskNode *)j;
|
||||||
short nrlen;
|
short nrlen;
|
||||||
|
|
||||||
BDB_DISK2ID( &d->entryID, &ei.bei_id );
|
BDB_DISK2ID( j + len - sizeof(ID), &ei.bei_id );
|
||||||
AC_MEMCPY( &nrlen, &d->nrdnlen, sizeof(d->nrdnlen) );
|
nrlen = ((d->nrdnlen[0] ^ 0x80) << 8) | d->nrdnlen[1];
|
||||||
ei.bei_nrdn.bv_len = nrlen;
|
ei.bei_nrdn.bv_len = nrlen;
|
||||||
/* nrdn/rdn are set in-place.
|
/* nrdn/rdn are set in-place.
|
||||||
* hdb_cache_load will copy them as needed
|
* hdb_cache_load will copy them as needed
|
||||||
|
@ -348,9 +348,9 @@ bdb_db_open( BackendDB *be )
|
|||||||
flags |= DB_CREATE;
|
flags |= DB_CREATE;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
#if 0
|
||||||
rc = db->bdi_db->set_dup_compare( db->bdi_db,
|
rc = db->bdi_db->set_dup_compare( db->bdi_db,
|
||||||
bdb_dup_compare );
|
bdb_dup_compare );
|
||||||
#if 0
|
|
||||||
rc = db->bdi_db->set_bt_compare( db->bdi_db,
|
rc = db->bdi_db->set_bt_compare( db->bdi_db,
|
||||||
bdb_bt_compare );
|
bdb_bt_compare );
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user