RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 23-Jul-2017 23:02:47 Branch: rpm-5_4 Handle: 2017072321024700 Modified files: (Branch: rpm-5_4) rpm/rpmdb lmdb.c Log: - lmdb: WIP. Summary: Revision Changes Path 1.1.2.6 +453 -176 rpm/rpmdb/lmdb.c ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/rpmdb/lmdb.c ============================================================================ $ cvs diff -u -r1.1.2.5 -r1.1.2.6 lmdb.c --- rpm/rpmdb/lmdb.c 23 Jul 2017 01:56:17 -0000 1.1.2.5 +++ rpm/rpmdb/lmdb.c 23 Jul 2017 21:02:47 -0000 1.1.2.6 @@ -181,6 +181,22 @@ return dbi->dbi_flags; } +/*==============================================================*/ +/* -- dbiset.c */ + +dbiIndexSet dbiIndexSetNew(unsigned int sizehint) +{ + dbiIndexSet set = xcalloc(1, sizeof(*set)); + if (sizehint > 0) + dbiIndexSetGrow(set, sizehint); + return set; +} + +/* + * Ensure sufficient memory for nrecs of new records in dbiIndexSet. + * Allocate in power of two sizes to avoid memory fragmentation, so + * realloc is not always needed. + */ void dbiIndexSetGrow(dbiIndexSet set, unsigned int nrecs) { size_t need = (set->count + nrecs) * sizeof(*(set->recs)); @@ -202,6 +218,43 @@ return (*a - *b); } +void dbiIndexSetSort(dbiIndexSet set) +{ + /* + * mergesort is much (~10x with lots of identical basenames) faster + * than pure quicksort, but glibc uses msort_with_tmp() on stack. + */ + if (set && set->recs && set->count > 1) { +#if HAVE_MERGESORT_XXX + mergesort(set->recs, set->count, sizeof(*set->recs), hdrNumCmp); +#else + qsort(set->recs, set->count, sizeof(*set->recs), hdrNumCmp); +#endif + } +} + +void dbiIndexSetUniq(dbiIndexSet set, int sorted) +{ + unsigned int from; + unsigned int to = 0; + unsigned int num = set->count; + + assert(set->count > 0); + + if (!sorted) + dbiIndexSetSort(set); + + for (from = 0; from < num; from++) { + if (from > 0 && set->recs[from - 1].hdrNum == set->recs[from].hdrNum) { + set->count--; + continue; + } + if (from != to) + set->recs[to] = set->recs[from]; /* structure assignment */ + to++; + } +} + int dbiIndexSetAppendSet(dbiIndexSet dest, dbiIndexSet src, int sortset) { if (dest == NULL || src == NULL || src->count == 0) @@ -217,70 +270,88 @@ return 0; } -dbiIndexSet dbiIndexSetFree(dbiIndexSet set) +int dbiIndexSetAppend(dbiIndexSet set, dbiIndexItem recs, + unsigned int nrecs, int sortset) { - if (set) { - free(set->recs); - free(set); - } - return NULL; -} + if (set == NULL || recs == NULL || nrecs == 0) + return 1; -dbiIndexSet dbiIndexSetNew(unsigned int sizehint) -{ - dbiIndexSet set = xcalloc(1, sizeof(*set)); - if (sizehint > 0) - dbiIndexSetGrow(set, sizehint); - return set; -} + dbiIndexSetGrow(set, nrecs); + memcpy(set->recs + set->count, recs, nrecs * sizeof(*(set->recs))); + set->count += nrecs; + + if (sortset && set->count > 1) + qsort(set->recs, set->count, sizeof(*(set->recs)), hdrNumCmp); -#define rpmChrootDone() (0) + return 0; +} -RPM_GNUC_PURE -const char *rpmdbHome(rpmdb db) +int dbiIndexSetPrune(dbiIndexSet set, dbiIndexItem recs, + unsigned int nrecs, int sorted) { - const char *dbdir = NULL; - if (db) { - dbdir = rpmChrootDone() ? db->db_home : db->db_fullpath; + unsigned int from; + unsigned int to = 0; + unsigned int num = set->count; + unsigned int numCopied = 0; + size_t recsize = sizeof(*recs); + + assert(set->count > 0); + if (nrecs > 1 && !sorted) + qsort(recs, nrecs, recsize, hdrNumCmp); + + for (from = 0; from < num; from++) { + if (bsearch(&set->recs[from], recs, nrecs, recsize, hdrNumCmp)) { + set->count--; + continue; + } + if (from != to) + set->recs[to] = set->recs[from]; /* structure assignment */ + to++; + numCopied++; } - return dbdir; + return (numCopied == num); } -/*==============================================================*/ -#ifndef DYING -typedef struct rpmidxdb_s *rpmidxdb; - -RPM_GNUC_CONST -void rpmidxClose(rpmidxdb idxdb) +RPM_GNUC_PURE +unsigned int dbiIndexSetCount(dbiIndexSet set) { + return (set != NULL) ? set->count : 0; } -RPM_GNUC_CONST -int rpmidxGet(rpmidxdb idxdb, const unsigned char *key, unsigned int keyl, unsigned int **pkgidxlistp, unsigned int *pkgidxnump) +RPM_GNUC_PURE +unsigned int dbiIndexRecordOffset(dbiIndexSet set, unsigned int recno) { - return RPMRC_FAIL; + return set->recs[recno].hdrNum; } -RPM_GNUC_CONST -int rpmidxPut(rpmidxdb idxdb, const unsigned char *key, unsigned int keyl, unsigned int pkgidx, unsigned int datidx) +RPM_GNUC_PURE +unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, unsigned int recno) { - return RPMRC_FAIL; + return set->recs[recno].tagNum; } -RPM_GNUC_CONST -int rpmidxDel(rpmidxdb idxdb, const unsigned char *key, unsigned int keyl, unsigned int pkgidx, unsigned int datidx) +dbiIndexSet dbiIndexSetFree(dbiIndexSet set) { - return RPMRC_FAIL; + if (set) { + free(set->recs); + memset(set, 0, sizeof(*set)); /* trash and burn */ + free(set); + } + return NULL; } -RPM_GNUC_CONST -int rpmidxList(rpmidxdb idxdb, unsigned int **keylistp, unsigned int *nkeylistp, unsigned char **datap) +/*==============================================================*/ +#define rpmChrootDone() (0) +RPM_GNUC_PURE +const char *rpmdbHome(rpmdb db) { - return RPMRC_FAIL; + const char *dbdir = NULL; + if (db) { + dbdir = rpmChrootDone() ? db->db_home : db->db_fullpath; + } + return dbdir; } -#endif - /*==============================================================*/ struct dbiCursor_s { @@ -554,6 +625,110 @@ return rc; } +static int dbiCursorPut(dbiCursor dbc, MDB_val * key, MDB_val * data, unsigned int flags) +{ + int rc = EINVAL; + int sane = (key->mv_data != NULL && key->mv_size > 0 && + data->mv_data != NULL && data->mv_size > 0); + + if (dbc && sane) { +#ifdef FIXME + DBC * cursor = dbc->cursor; + rpmdb rdb = dbc->dbi->dbi_rpmdb; + rpmswEnter(&rdb->db_putops, (ssize_t) 0); + + rc = cursor->c_put(cursor, key, data, MDB_LAST); + rc = cvtdberr(dbc->dbi, "dbcursor->c_put", rc, _debug); + + rpmswExit(&rdb->db_putops, (ssize_t) data->size); +#endif + } +SPEW("<-- %s(%p,key,data,0x%x) rc %d\n", __FUNCTION__, dbc, flags, rc); + return rc; +} + +static int dbiCursorGet(dbiCursor dbc, MDB_val * key, MDB_val * data, unsigned int flags) +{ + int rc = EINVAL; + int sane = ((flags == MDB_NEXT) || (key->mv_data != NULL && key->mv_size > 0)); + + if (dbc && sane) { +#ifdef FIXME + DBC * cursor = dbc->cursor; + rpmdb rdb = dbc->dbi->dbi_rpmdb; + int _printit; + rpmswEnter(&rdb->db_getops, 0); + + /* XXX db4 does DB_FIRST on uninitialized cursor */ + rc = cursor->c_get(cursor, key, data, flags); + /* XXX DB_NOTFOUND can be returned */ + _printit = (rc == DB_NOTFOUND ? 0 : _debug); + rc = cvtdberr(dbc->dbi, "dbcursor->c_get", rc, _printit); + + /* Remember the last key fetched */ + if (rc == 0) { + dbc->key = key->data; + dbc->keylen = key->size; + } else { + dbc->key = NULL; + dbc->keylen = 0; + } + + rpmswExit(&rdb->db_getops, data->size); +#endif + } +SPEW("<-- %s(%p,key,data,0x%x) rc %d\n", __FUNCTION__, dbc, flags, rc); + return rc; +} + +static int dbiCursorDel(dbiCursor dbc, MDB_val * key, MDB_val * data, unsigned int flags) +{ + int rc = EINVAL; + int sane = (key->mv_data != NULL && key->mv_size > 0); + + if (dbc && sane) { +#ifdef FIXME + 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); +#endif + } +SPEW("<-- %s(%p,key,data,0x%x) rc %d\n", __FUNCTION__, dbc, flags, rc); + return rc; +} + +static int dbiByteSwapped(dbiIndex dbi) +{ + int rc = 0; +#ifdef FIXME + DB * db = dbi->dbi_db; + + if (dbi->dbi_byteswapped != -1) + return dbi->dbi_byteswapped; + + if (db != NULL) { + int isswapped = 0; + rc = db->get_byteswapped(db, &isswapped); + if (rc == 0) + dbi->dbi_byteswapped = rc = isswapped; + } +#endif + return rc; +} + static dbiCursor lmdb_CursorInit(dbiIndex dbi, unsigned int flags) { dbiCursor dbc = xcalloc(1, sizeof(*dbc)); @@ -666,40 +841,6 @@ return rc; } -/* iterate over all packages */ -static rpmRC lmdb_pkgdbIter(dbiIndex dbi, dbiCursor dbc, unsigned char **hdrBlob, unsigned int *hdrLen) -{ - int rc = RPMRC_FAIL; - -#ifdef FIXME - unsigned int hdrNum; - - if (!dbc->list) { - rc = rpmpkgList(dbc->dbi->dbi_db, &dbc->list, &dbc->nlist); - if (rc) - return rc; - dbc->ilist = 0; - } - for (;;) { - if (dbc->ilist >= dbc->nlist) { - rc = RPMRC_NOTFOUND; - break; - } - *hdrBlob = 0; - hdrNum = dbc->list[dbc->ilist]; -#ifdef FIXME - rc = rpmpkgGet(dbc->dbi->dbi_db, hdrNum, hdrBlob, hdrLen); -#endif - if (rc && rc != RPMRC_NOTFOUND) - break; - dbc->ilist++; - } -#endif - -SPEW("<-- %s(%p,%p,%p,%p) rc %d\n", __FUNCTION__, dbi, dbc, hdrBlob, hdrLen, rc); - return rc; -} - static rpmRC lmdb_pkgdbGet(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char **hdrBlob, unsigned int *hdrLen) { int rc = RPMRC_FAIL; @@ -742,137 +883,273 @@ return rc; } +union _dbswap { + unsigned int ui; + unsigned char uc[4]; +}; -static void addtoset(dbiIndexSet *set, unsigned int *pkglist, unsigned int pkglistn) -{ - unsigned int i, j; - dbiIndexSet newset = dbiIndexSetNew(pkglistn / 2); - for (i = j = 0; i < pkglistn; i += 2) { - newset->recs[j].hdrNum = pkglist[i]; - newset->recs[j].tagNum = pkglist[i + 1]; - j++; +#define _DBSWAP(_a) \ +\ + { unsigned char _b, *_c = (_a).uc; \ + _b = _c[3]; _c[3] = _c[0]; _c[0] = _b; \ + _b = _c[2]; _c[2] = _c[1]; _c[1] = _b; \ +\ + } + +/** + * Convert retrieved data to index set. + * @param dbi index database handle + * @param data retrieved data + * @retval setp (malloc'ed) index set + * @return 0 on success + */ +static int dbt2set(dbiIndex dbi, MDB_val * data, dbiIndexSet * setp) +{ + int _dbbyteswapped = dbiByteSwapped(dbi); + const char * sdbir; + dbiIndexSet set; + unsigned int i; + + if (dbi == NULL || data == NULL || setp == NULL) + return -1; + + if ((sdbir = data->mv_data) == NULL) { + *setp = NULL; + return 0; + } + + set = dbiIndexSetNew(data->mv_size / (2 * sizeof(int32_t))); + set->count = data->mv_size / (2 * sizeof(int32_t)); + + for (i = 0; i < set->count; i++) { + union _dbswap hdrNum, tagNum; + + memcpy(&hdrNum.ui, sdbir, sizeof(hdrNum.ui)); + sdbir += sizeof(hdrNum.ui); + memcpy(&tagNum.ui, sdbir, sizeof(tagNum.ui)); + sdbir += sizeof(tagNum.ui); + if (_dbbyteswapped) { + _DBSWAP(hdrNum); + _DBSWAP(tagNum); + } + set->recs[i].hdrNum = hdrNum.ui; + set->recs[i].tagNum = tagNum.ui; } - newset->count = j; - if (pkglist) - free(pkglist); - if (*set) { - dbiIndexSetAppendSet(*set, newset, 0); - dbiIndexSetFree(newset); - } else - *set = newset; + *setp = set; + return 0; +} + +/** + * Convert index set to database representation. + * @param dbi index database handle + * @param data retrieved data + * @param set index set + * @return 0 on success + */ +static int set2dbt(dbiIndex dbi, MDB_val * data, dbiIndexSet set) +{ + int _dbbyteswapped = dbiByteSwapped(dbi); + char * tdbir; + unsigned int i; + + if (dbi == NULL || data == NULL || set == NULL) + return -1; + + data->mv_size = set->count * (2 * sizeof(int32_t)); + if (data->mv_size == 0) { + data->mv_data = NULL; + return 0; + } + tdbir = data->mv_data = xmalloc(data->mv_size); + + for (i = 0; i < set->count; i++) { + union _dbswap hdrNum, tagNum; + + memset(&hdrNum, 0, sizeof(hdrNum)); + memset(&tagNum, 0, sizeof(tagNum)); + hdrNum.ui = set->recs[i].hdrNum; + tagNum.ui = set->recs[i].tagNum; + if (_dbbyteswapped) { + _DBSWAP(hdrNum); + _DBSWAP(tagNum); + } + memcpy(tdbir, &hdrNum.ui, sizeof(hdrNum.ui)); + tdbir += sizeof(hdrNum.ui); + memcpy(tdbir, &tagNum.ui, sizeof(tagNum.ui)); + tdbir += sizeof(tagNum.ui); + } + return 0; } -/* Iterate over all index entries */ -static rpmRC lmdb_idxdbIter(dbiIndex dbi, dbiCursor dbc, dbiIndexSet *set) +static rpmRC lmdb_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexSet *set, int searchType) { - int rc = RPMRC_FAIL; + rpmRC rc = RPMRC_FAIL; -#ifdef FIXME - if (!dbc->list) { - /* setup iteration list on first call */ - rc = rpmidxList(dbc->dbi->dbi_db, &dbc->list, &dbc->nlist, &dbc->listdata); - if (rc) - return rc; - dbc->ilist = 0; + if (dbi == NULL || dbc == NULL || set == NULL) + goto exit; + + int cflags = MDB_NEXT; + int dbrc; + MDB_val key = { 0, NULL }; + MDB_val data = { 0, NULL }; + + if (keyp) { + if (keylen == 0) { /* XXX "/" fixup */ + keyp = ""; + keylen = 1; + } + key.mv_data = (void *) keyp; /* discards const */ + key.mv_size = keylen; + cflags = searchType == DBC_PREFIX_SEARCH ? MDB_SET_RANGE : MDB_SET; } + for (;;) { - unsigned char *k; - unsigned int kl; - unsigned int *pkglist, pkglistn; - if (dbc->ilist >= dbc->nlist) { - rc = RPMRC_NOTFOUND; + dbiIndexSet newset = NULL; + dbrc = dbiCursorGet(dbc, &key, &data, cflags); + if (dbrc != 0) break; - } - k = dbc->listdata + dbc->list[dbc->ilist]; - kl = dbc->list[dbc->ilist + 1]; -#if 0 - if (searchType == DBC_KEY_SEARCH) { - dbc->ilist += 2; - dbc->key = k; - dbc->keylen = kl; - rc = RPMRC_OK; + if (searchType == DBC_PREFIX_SEARCH + && (key.mv_size < keylen || memcmp(key.mv_data, keyp, keylen) != 0)) break; + dbt2set(dbi, &data, &newset); + if (*set == NULL) { + *set = newset; + } else { + dbiIndexSetAppendSet(*set, newset, 0); + dbiIndexSetFree(newset); } -#endif - pkglist = 0; - pkglistn = 0; - rc = rpmidxGet(dbc->dbi->dbi_db, k, kl, &pkglist, &pkglistn); - if (rc && rc != RPMRC_NOTFOUND) - break; - dbc->ilist += 2; - if (!rc && pkglistn) { - addtoset(set, pkglist, pkglistn); - dbc->key = k; - dbc->keylen = kl; + if (searchType != DBC_PREFIX_SEARCH) break; + key.mv_data = NULL; + key.mv_size = 0; + cflags = MDB_NEXT; + } + + /* fixup result status for prefix search */ + if (searchType == DBC_PREFIX_SEARCH) { + if (dbrc == MDB_NOTFOUND && *set != NULL && (*set)->count > 0) + dbrc = MDB_SUCCESS; + else if (dbrc == 0 && (*set == NULL || (*set)->count == 0)) + dbrc = MDB_NOTFOUND; + } + + switch (dbrc) { + case MDB_SUCCESS: + rc = RPMRC_OK; + break; + case MDB_NOTFOUND: + rc = RPMRC_NOTFOUND; + break; + default: + rc = RPMRC_FAIL; + rpmlog(RPMLOG_ERR, + _("error(%d) getting \"%s\" records from %s index: %s\n"), + dbrc, keyp ? keyp : "???", dbiName(dbi), mdb_strerror(dbrc)); + break; + } + +exit: +SPEW("<-- %s(%p,%p,%p[%u],%p,0x%x) rc %d\n", __FUNCTION__, dbi, dbc, keyp, (unsigned)keylen, set, searchType, rc); + return rc; +} + +/* Update secondary index. NULL set deletes the key */ +static rpmRC updateIndex(dbiCursor dbc, const char *keyp, unsigned int keylen, + dbiIndexSet set) +{ + rpmRC rc = RPMRC_FAIL; + + if (dbc && keyp) { + dbiIndex dbi = dbc->dbi; + int dbrc; + MDB_val key = { 0, NULL }; + MDB_val data = { 0, NULL }; + + key.mv_data = (void *) keyp; /* discards const */ + key.mv_size = keylen; + + if (set) + set2dbt(dbi, &data, set); + + if (dbiIndexSetCount(set) > 0) { + dbrc = dbiCursorPut(dbc, &key, &data, MDB_LAST); + if (dbrc) { + rpmlog(RPMLOG_ERR, + _("error(%d) storing record \"%s\" into %s\n"), + dbrc, (char*)key.mv_data, dbiName(dbi)); + } + free(data.mv_data); + } else { + dbrc = dbiCursorDel(dbc, &key, &data, 0); + if (dbrc) { + rpmlog(RPMLOG_ERR, + _("error(%d) removing record \"%s\" from %s\n"), + dbrc, (char*)key.mv_data, dbiName(dbi)); + } } - if (pkglist) - free(pkglist); + + if (dbrc == 0) + rc = RPMRC_OK; } -#endif -SPEW("<-- %s(%p,%p,%p) rc %d\n", __FUNCTION__, dbi, dbc, set, rc); return rc; } -static rpmRC lmdb_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexSet *set, int searchType) +static rpmRC lmdb_idxdbPut(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexItem rec) { - int rc = RPMRC_FAIL; - unsigned int *pkglist = 0, pkglistn = 0; + dbiIndexSet set = NULL; + rpmRC rc = RPMRC_FAIL; - if (!keyp) { - rc = lmdb_idxdbIter(dbi, dbc, set); - goto exit; + if (keyp && keylen == 0) { /* XXX "/" fixup */ + keyp = ""; + keylen++; } + rc = lmdb_idxdbGet(dbi, dbc, keyp, keylen, &set, DBC_NORMAL_SEARCH); - if (searchType == DBC_PREFIX_SEARCH) { - unsigned int *list = 0, nlist = 0, i = 0; - unsigned char *listdata = 0; - int rrc = RPMRC_NOTFOUND; - rc = rpmidxList(dbc->dbi->dbi_db, &list, &nlist, &listdata); - if (rc) - goto exit; - for (i = 0; i < nlist && !rc; i += 2) { - unsigned char *k = listdata + list[i]; - unsigned int kl = list[i + 1]; - if (kl < keylen || memcmp(k, keyp, keylen) != 0) - continue; - rc = lmdb_idxdbGet(dbi, dbc, (char *)k, kl, set, DBC_NORMAL_SEARCH); - if (rc == RPMRC_NOTFOUND) - rc = 0; - else - rrc = rc; - } - if (list) - free(list); - if (listdata) - free(listdata); - if (!rc) - rc = rrc; + /* Not found means a new key and is not an error. */ + if (rc && rc != RPMRC_NOTFOUND) goto exit; - } - rc = rpmidxGet(dbc->dbi->dbi_db, (const unsigned char *)keyp, keylen, &pkglist, &pkglistn); - if (!rc) - addtoset(set, pkglist, pkglistn); + if (set == NULL) + set = dbiIndexSetNew(1); + dbiIndexSetAppend(set, rec, 1, 0); -exit: -SPEW("<-- %s(%p,%p,%p[%u],%p,0x%x) rc %d\n", __FUNCTION__, dbi, dbc, keyp, (unsigned)keylen, set, searchType, rc); - return rc; -} + rc = updateIndex(dbc, keyp, keylen, set); -static rpmRC lmdb_idxdbPut(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexItem rec) -{ - int rc = RPMRC_FAIL; - rc = rpmidxPut(dbc->dbi->dbi_db, (const unsigned char *)keyp, keylen, rec->hdrNum, rec->tagNum); + dbiIndexSetFree(set); + +exit: SPEW("<-- %s(%p,%p,%p[%u],%p) rc %d\n", __FUNCTION__, dbi, dbc, keyp, (unsigned)keylen, rec, rc); return rc; } static rpmRC lmdb_idxdbDel(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexItem rec) { - int rc = RPMRC_FAIL; - rc = rpmidxDel(dbc->dbi->dbi_db, (const unsigned char *)keyp, keylen, rec->hdrNum, rec->tagNum); + dbiIndexSet set = NULL; + rpmRC rc = RPMRC_FAIL; + + if (keyp && keylen == 0) { /* XXX "/" fixup */ + keyp = ""; + keylen++; + } + rc = lmdb_idxdbGet(dbi, dbc, keyp, keylen, &set, DBC_NORMAL_SEARCH); + if (rc) + goto exit; + + if (dbiIndexSetPrune(set, rec, 1, 1)) { + /* Nothing was pruned. XXX: Can this actually happen? */ + rc = RPMRC_OK; + } else { + /* If there's data left, update data. Otherwise delete the key. */ + if (dbiIndexSetCount(set) > 0) { + rc = updateIndex(dbc, keyp, keylen, set); + } else { + rc = updateIndex(dbc, keyp, keylen, NULL); + } + }; + dbiIndexSetFree(set); + +exit: SPEW("<-- %s(%p,%p,%p[%u],%p) rc %d\n", __FUNCTION__, dbi, dbc, keyp, (unsigned)keylen, rec, rc); return rc; } @@ -939,7 +1216,7 @@ } /* Unless we manage to insert the new instance number, we failed */ - ret = dbiCursorPut(dbc, &key, &data, DB_KEYLAST); + ret = dbiCursorPut(dbc, &key, &data, MDB_LAST); if (ret) { hdrNum = 0; rpmlog(RPMLOG_ERR, @@ -1104,12 +1381,12 @@ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_txn_abort(lmdbenv->txn); + lmdbenv->txn = NULL; j = 0; key.mv_data = sval; for (i = count - 1; i > -1; i -= (rand() % 5)) { j++; - lmdbenv->txn = NULL; E(mdb_txn_begin(lmdbenv->env, NULL, 0, &lmdbenv->txn)); sprintf(sval, "%03x ", values[i]); if (RES(MDB_NOTFOUND, mdb_del(lmdbenv->txn, dbi, &key, NULL))) { @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org