[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: using cursors in LDBM back end with gdbm (ITS#450)
At 11:15 PM 2/10/00 GMT, adamson@andrew.cmu.edu wrote:
>Programs such as slapindex that step through an LDBM back end database,
>entry by entry, use the cursor variable
>
>static LDBMCursor *cursorp = NULL;
>
>in servers/slapd/back-ldbm/tools.c to keep track where they are in the
>database. This cursorp variable is passed to ldbm_firstkey() and
>ldbm_nextkey(), and those functions are expected to do their own database
>dependant method of cursoring.
In 1.2 or devel codes? In 1.2, the code works because the
caller copies key to last before calling ldbm_nextkey().
In devel, the code appears to be broken in that back-ldbm is
assuming cursor support which LDBM doesn't provide. The
solution here is to either have back-ldbm manage a last key
or have LDBM manage the last key as a "cursor". The cursor
approach would be better as it makes LDBM job is to deal
with differnet capabilities of the underlying database engine.
A patch to fix this would be quite welcomed. See
http://www.openldap.org/devel/contributing.html for details.
>Those firstkey and nextkey functions appear in libraries/libldbm/ldbm.c,
>once for each type of database (dbm, ndbm, gdbm, etc). The gdbm (and dbm)
>version of ldbm_firstkey() and ldbm_lastkey() do not make use of the
>cursor variable! Instead, the "key" variable is passed to the
>gdbm_nextkey() function as the cursor, and that "key" variable is
>just a local variable in the calling function, so it has junk in it from
>the stack. The result is that the value returned by gdbm_nextkey() is
>indeterminant, (but most likely a "not found" value).
>
>ldbm_firstkey() and ldbm_lastkey() need to do the ugly task of copying
>fetched values into the cursor. The data fetched will most likely be
>free'd before the next call to ldbm_nextkey(), so a complete copy must be
>made.
>
>Here is the reimplementation of those too functions that I wrote and am
>using. They are for gdbm, and similar versions could be made for dbm.
>(As you can probably guess, I'm not real clear on this whole CVS checkin
>thang).
>
>-Mark Adamson
> Carnegie Mellon University
>
>
>
>libraries/libldbm/ldbm.c
>circa line 523 in version 1.36
>
>
>Datum
>ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
>{
> Datum d, *cur;
>
> LDBM_LOCK;
> d = gdbm_firstkey( ldbm );
> LDBM_UNLOCK;
>
> /* Store the first key in the cursor */
> if (*dbcp) free (*dbcp);
> cur = (Datum *)malloc(sizeof(Datum));
> if (cur) {
> cur->dsize = d.dsize;
> if (cur->dsize) {
> cur->dptr = (char *)malloc(cur->dsize);
> if (cur->dptr)
> memcpy(cur->dptr, d.dptr, cur->dsize);
> else {
> free(cur);
> cur = NULL;
> }
> }
> else
> cur->dptr = NULL;
> }
> *dbcp = (LDBMCursor *)cur;
>
>
> return d;
>}
>
>Datum
>ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
>{
> Datum *cur;
>
> /* Load the cursor into the key */
> cur = (Datum *)dbcp;
> if (cur == NULL) {
> key.dptr = 0;
> key.dsize = 0;
> return key;
> }
> key.dptr = cur->dptr;
> key.dsize = cur->dsize;
>
> LDBM_LOCK;
> key = gdbm_nextkey( ldbm, key );
> LDBM_UNLOCK;
>
> /* Save this datum back into the key */
> if (cur->dsize == key.dsize) /* Reuse the same dptr space */
> memcpy(cur->dptr, key.dptr, cur->dsize);
> else {
> cur->dsize = key.dsize;
> cur->dptr = (char *)realloc(cur->dptr, cur->dsize);
> if (cur->dsize) {
> if (cur->dptr) memcpy(cur->dptr, key.dptr,
>cur->dsize);
> else cur->dsize = 0;
> }
> else
> cur->dptr = NULL;
> }
> return key;
>}
>
>
>