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

Reply via email to