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: 22-Jul-2017 22:11:05 Branch: rpm-5_4 Handle: 2017072220110500 Modified files: (Branch: rpm-5_4) rpm/rpmdb lmdb.c Log: - lmdb: WIP. Summary: Revision Changes Path 1.1.2.3 +391 -365 rpm/rpmdb/lmdb.c ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/rpmdb/lmdb.c ============================================================================ $ cvs diff -u -r1.1.2.2 -r1.1.2.3 lmdb.c --- rpm/rpmdb/lmdb.c 22 Jul 2017 14:19:33 -0000 1.1.2.2 +++ rpm/rpmdb/lmdb.c 22 Jul 2017 20:11:05 -0000 1.1.2.3 @@ -55,9 +55,18 @@ struct rpmdbOps_s; -/** \ingroup rpmdb - * Describes the collection of index databases used by rpm. - */ +struct dbiIndex_s { + rpmdb dbi_rpmdb; /*!< the parent rpm database */ + dbiIndexType dbi_type; /*! Type of dbi (primary / index) */ + const char * dbi_file; /*!< file component of path */ + int dbi_flags; + int dbi_byteswapped; + + struct dbiConfig_s cfg; + + void * dbi_db; /*!< Backend private handle */ +}; + struct rpmdb_s { char * db_root;/*!< path prefix */ char * db_home;/*!< directory path */ @@ -176,6 +185,37 @@ } } +/* XXX assumes hdrNum is first int in dbiIndexItem */ +static int hdrNumCmp(const void * one, const void * two) +{ + const unsigned int * a = one, * b = two; + return (*a - *b); +} + +int dbiIndexSetAppendSet(dbiIndexSet dest, dbiIndexSet src, int sortset) +{ + if (dest == NULL || src == NULL || src->count == 0) + return 1; + + dbiIndexSetGrow(dest, src->count); + memcpy(dest->recs + dest->count, + src->recs, src->count * sizeof(*src->recs)); + dest->count += src->count; + + if (sortset && dest->count > 1) + qsort(dest->recs, dest->count, sizeof(*(dest->recs)), hdrNumCmp); + return 0; +} + +dbiIndexSet dbiIndexSetFree(dbiIndexSet set) +{ + if (set) { + free(set->recs); + free(set); + } + return NULL; +} + dbiIndexSet dbiIndexSetNew(unsigned int sizehint) { dbiIndexSet set = xcalloc(1, sizeof(*set)); @@ -197,154 +237,7 @@ } /*==============================================================*/ -typedef struct rpmpkgdb_s * rpmpkgdb; - -RPM_GNUC_CONST -void rpmpkgClose(rpmpkgdb pkgdb) -{ -} - -RPM_GNUC_CONST -int rpmpkgOpen(rpmpkgdb *pkgdbp, const char *filename, int flags, int mode) -{ - return RPMRC_FAIL; -} - -static int rpmpkgGetLock(rpmpkgdb pkgdb, int type) -{ -#ifdef NOTYET - if (!pkgdb->fd) - return RPMRC_FAIL; - for (;;) { - if (flock(pkgdb->fd, type)) { - return RPMRC_FAIL; - } - if (!is_correct_db(pkgdb)) { - if (reopen_db(pkgdb)) { - return RPMRC_FAIL; - } - continue; - } - break; - } -#endif - return RPMRC_OK; -} - -RPM_GNUC_CONST -int rpmpkgLock(rpmpkgdb pkgdb, int excl) -{ -#ifdef NOTYET - unsigned int *lockcntp = excl ? &pkgdb->locked_excl : &pkgdb->locked_shared; - if (*lockcntp > 0 || (!excl && pkgdb->locked_excl)) { - (*lockcntp)++; - return RPMRC_OK; - } - pkgdb->header_ok = 0; - if (rpmpkgGetLock(pkgdb, excl ? LOCK_EX : LOCK_SH)) { - return RPMRC_FAIL; - } - (*lockcntp)++; -#endif - return RPMRC_OK; -} - -RPM_GNUC_CONST -int rpmpkgUnlock(rpmpkgdb pkgdb, int excl) -{ -#ifdef NOTYET - unsigned int *lockcntp = excl ? &pkgdb->locked_excl : &pkgdb->locked_shared; - if (*lockcntp == 0) { - return RPMRC_FAIL; - } - if (*lockcntp > 1 || (!excl && pkgdb->locked_excl)) { - (*lockcntp)--; - return RPMRC_OK; - } - if (excl && pkgdb->locked_shared) { - /* excl -> shared switch */ - if (rpmpkgGetLock(pkgdb, LOCK_SH)) { - return RPMRC_FAIL; - } - (*lockcntp)--; - return RPMRC_OK; - } - flock(pkgdb->fd, LOCK_UN); - (*lockcntp)--; - pkgdb->header_ok = 0; -#endif - return RPMRC_OK; -} - -RPM_GNUC_CONST -int rpmpkgGet(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned char **blobp, unsigned int *bloblp) -{ - return RPMRC_FAIL; -} - -RPM_GNUC_CONST -int rpmpkgPut(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned char *blob, unsigned int blobl) -{ - return RPMRC_FAIL; -} - -RPM_GNUC_CONST -int rpmpkgDel(rpmpkgdb pkgdb, unsigned int pkgidx) -{ - return RPMRC_FAIL; -} - -RPM_GNUC_CONST -int rpmpkgList(rpmpkgdb pkgdb, unsigned int **pkgidxlistp, unsigned int *npkgidxlistp) -{ - return RPMRC_FAIL; -} - -RPM_GNUC_CONST -int rpmpkgGeneration(rpmpkgdb pkgdb, unsigned int *generationp) -{ - return RPMRC_FAIL; -} - -RPM_GNUC_CONST -int rpmpkgNextPkgIdx(rpmpkgdb pkgdb, unsigned int *pkgidxp) -{ - return RPMRC_FAIL; -} - -/*==============================================================*/ -typedef struct rpmxdb_s * rpmxdb; - -RPM_GNUC_CONST -void rpmxdbClose(rpmxdb xdb) -{ -} - -RPM_GNUC_CONST -int rpmxdbOpen(rpmxdb *xdbp, rpmpkgdb pkgdb, const char *filename, int flags, int mode) -{ - return RPMRC_FAIL; -} - -RPM_GNUC_CONST -int rpmxdbLookupBlob(rpmxdb xdb, unsigned int *idp, unsigned int blobtag, unsigned int subtag, int flags) -{ - return RPMRC_FAIL; -} - -RPM_GNUC_CONST -int rpmxdbIsRdonly(rpmxdb xdb) -{ - return 1; -} - -RPM_GNUC_CONST -int rpmxdbSetUserGeneration(rpmxdb xdb, unsigned int usergeneration) -{ - return RPMRC_FAIL; -} - -/*==============================================================*/ +#ifndef DYING typedef struct rpmidxdb_s *rpmidxdb; RPM_GNUC_CONST @@ -353,12 +246,6 @@ } RPM_GNUC_CONST -int rpmidxOpen(rpmidxdb *idxdbp, rpmpkgdb pkgdb, const char *filename, int flags, int mode) -{ - return RPMRC_FAIL; -} - -RPM_GNUC_CONST int rpmidxGet(rpmidxdb idxdb, const unsigned char *key, unsigned int keyl, unsigned int **pkgidxlistp, unsigned int *pkgidxnump) { return RPMRC_FAIL; @@ -382,11 +269,7 @@ return RPMRC_FAIL; } -RPM_GNUC_CONST -int rpmidxOpenXdb(rpmidxdb *idxdbp, rpmpkgdb pkgdb, rpmxdb xdb, unsigned int xdbtag) -{ - return RPMRC_FAIL; -} +#endif /*==============================================================*/ @@ -396,47 +279,101 @@ unsigned int keylen; unsigned int hdrNum; int flags; + MDB_cursor * cursor; +}; - unsigned int *list; - unsigned int nlist; - unsigned int ilist; - unsigned char *listdata; +struct lmdbDbi_s { + MDB_dbi dbi; }; struct lmdbEnv_s { - rpmpkgdb pkgdb; - rpmxdb xdb; + MDB_env * env; int refs; - - unsigned int hdrNum; - void *data; - unsigned int datalen; }; static void closeEnv(rpmdb rdb) { struct lmdbEnv_s *lmdbenv = rdb->db_dbenv; - if (--lmdbenv->refs == 0) { - if (lmdbenv->xdb) { - rpmxdbClose(lmdbenv->xdb); - rpmlog(RPMLOG_DEBUG, "closed db index %s/Index.db\n", rpmdbHome(rdb)); - } - if (lmdbenv->pkgdb) { - rpmpkgClose(lmdbenv->pkgdb); - rpmlog(RPMLOG_DEBUG, "closed db index %s/Packages.db\n", rpmdbHome(rdb)); - } - if (lmdbenv->data) - free(lmdbenv->data); + if (--lmdbenv->refs <= 0) { + const char *dbhome = rpmdbHome(rdb); + MDB_env * env = (MDB_env *) lmdbenv->env; + if (env) + mdb_env_close(env); + rpmlog(RPMLOG_DEBUG, "closed db environment %s\n", dbhome); + lmdbenv->env = NULL; free(lmdbenv); - rdb->db_dbenv = 0; + rdb->db_dbenv = NULL; } } +static void lmdb_assert(MDB_env *env, const char *msg) +{ + fprintf(stderr, "%s: %s\n", __FUNCTION__, msg); +} + static struct lmdbEnv_s *openEnv(rpmdb rdb) { struct lmdbEnv_s *lmdbenv = rdb->db_dbenv; - if (!lmdbenv) + + if (!lmdbenv) { + const char *dbhome = rpmdbHome(rdb); + unsigned int maxreaders = 16; + MDB_dbi maxdbs = 64; + mdb_size_t mapsize = 10 * 1024 * 1024; + MDB_env * env = NULL; + int rc; + + if (mdb_env_create(&env) + || mdb_env_set_maxreaders(env, maxreaders) + || mdb_env_set_maxdbs(env, maxdbs) + || mdb_env_set_mapsize(env, mapsize) + || mdb_env_set_assert(env, lmdb_assert) + || mdb_env_set_userctx(env, rdb)) + return NULL; + + const char * path = dbhome; + + int flags = ( +#ifdef REF + MDB_FIXEDMAP | + MDB_NOSUBDIR | + MDB_RDONLY | + MDB_WRITEMAP | + MDB_WRITEMAP | + MDB_NOMETASYNC | + MDB_NOSYNC | + MDB_MAPASYNC | + MDB_NOTLS | + MDB_NOLOCK | + MDB_NORDAHEAD | + MDB_MEMINIT | +#endif + 0 + ); + flags |= MDB_FIXEDMAP; + + mode_t mode = 0644; + + rpmlog(RPMLOG_DEBUG, "opening db environment %s flags 0x%x mode 0%o\n", path, flags, mode); + + rc = mdb_env_open(env, path, flags, mode); + switch (rc) { + case MDB_SUCCESS: + break; + case MDB_VERSION_MISMATCH: + case MDB_INVALID: + case ENOENT: + case EACCES: + case EAGAIN: + default: + break; + } + if (rc) + return NULL; + rdb->db_dbenv = lmdbenv = xcalloc(1, sizeof(struct lmdbEnv_s)); + lmdbenv->env = env; + } lmdbenv->refs++; return lmdbenv; } @@ -444,22 +381,21 @@ static int lmdb_Close(dbiIndex dbi, unsigned int flags) { rpmdb rdb = dbi->dbi_rpmdb; - if (dbi->dbi_type != DBI_PRIMARY && dbi->dbi_db) { - rpmidxClose(dbi->dbi_db); - rpmlog(RPMLOG_DEBUG, "closed db index %s\n", dbi->dbi_file); - } + struct lmdbEnv_s * lmdbenv = rdb->db_dbenv; + struct lmdbDbi_s * lmdbdbi = (struct lmdbDbi_s *) dbi->dbi_db; + MDB_env * env = lmdbenv->env; + mdb_dbi_close(env, lmdbdbi->dbi); + rpmlog(RPMLOG_DEBUG, "closed db index %s\n", dbi->dbi_file); if (rdb->db_dbenv) closeEnv(rdb); - dbi->dbi_db = 0; + dbi->dbi_db = NULL; return 0; } static int lmdb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags) { const char *dbhome = rpmdbHome(rdb); - struct lmdbEnv_s *lmdbenv; dbiIndex dbi; - int oflags, ioflags; int rc = -1; if (dbip) @@ -468,86 +404,80 @@ if ((dbi = dbiNew(rdb, rpmtag)) == NULL) return 1; - lmdbenv = openEnv(rdb); + struct lmdbDbi_s * lmdbdbi = (struct lmdbDbi_s *) xcalloc(1, sizeof(*lmdbdbi)); + struct lmdbEnv_s * lmdbenv = openEnv(rdb); + MDB_env * env = lmdbenv->env; + char * path; + + int oflags = ( +#ifdef REF + MDB_REVERSEKEY | + MDB_DUPSORT | + MDB_INTEGERKEY | + MDB_DUPFIXED | + MDB_INTEGERDUP | + MDB_REVERSEDUP | + MDB_CREATE | +#endif + 0 + ); + oflags |= MDB_CREATE; - oflags = O_RDWR; - if ((rdb->db_mode & O_ACCMODE) == O_RDONLY) - oflags = O_RDONLY; - if (dbi->dbi_type == DBI_PRIMARY) { - rpmpkgdb pkgdb = 0; - char *path = rpmGetPath(dbhome, "/Packages.db", NULL); + path = rpmGetPath(dbhome, "/Packages", NULL); rpmlog(RPMLOG_DEBUG, "opening db index %s mode=0x%x\n", path, rdb->db_mode); - rc = rpmpkgOpen(&pkgdb, path, oflags, 0666); - if (rc && errno == ENOENT) { - oflags = O_RDWR|O_CREAT; - dbi->dbi_flags |= DBI_CREATED; - rc = rpmpkgOpen(&pkgdb, path, oflags, 0666); - } - if (rc) { - perror("rpmpkgOpen"); - free(path); - lmdb_Close(dbi, 0); - return 1; - } - free(path); - dbi->dbi_db = lmdbenv->pkgdb = pkgdb; - - if ((oflags & (O_RDWR | O_RDONLY)) == O_RDONLY) - dbi->dbi_flags |= DBI_RDONLY; + oflags |= MDB_INTEGERKEY; } else { - unsigned int id; - rpmidxdb idxdb = 0; - if (!lmdbenv->pkgdb) { - lmdb_Close(dbi, 0); - return 1; /* please open primary first */ - } - if (!lmdbenv->xdb) { - char *path = rpmGetPath(dbhome, "/Index.db", NULL); - rpmlog(RPMLOG_DEBUG, "opening db index %s mode=0x%x\n", path, rdb->db_mode); - - /* Open indexes readwrite if possible */ - ioflags = O_RDWR; - rc = rpmxdbOpen(&lmdbenv->xdb, rdb->db_pkgs->dbi_db, path, ioflags, 0666); - if (rc && errno == EACCES) { - /* If it is not asked for rw explicitly, try to open ro */ - if (!(oflags & O_RDWR)) { - ioflags = O_RDONLY; - rc = rpmxdbOpen(&lmdbenv->xdb, rdb->db_pkgs->dbi_db, path, ioflags, 0666); - } - } else if (rc && errno == ENOENT) { - ioflags = O_CREAT|O_RDWR; - rc = rpmxdbOpen(&lmdbenv->xdb, rdb->db_pkgs->dbi_db, path, ioflags, 0666); - } - if (rc) { - perror("rpmxdbOpen"); - free(path); - lmdb_Close(dbi, 0); - return 1; - } - free(path); - } - if (rpmxdbLookupBlob(lmdbenv->xdb, &id, rpmtag, 0, 0) == RPMRC_NOTFOUND) { - dbi->dbi_flags |= DBI_CREATED; - } - rpmlog(RPMLOG_DEBUG, "opening db index %s tag=%d\n", dbiName(dbi), rpmtag); - if (rpmidxOpenXdb(&idxdb, rdb->db_pkgs->dbi_db, lmdbenv->xdb, rpmtag)) { - perror("rpmidxOpenXdb"); - lmdb_Close(dbi, 0); - return 1; - } - dbi->dbi_db = idxdb; + path = rpmGetPath(dbhome, dbi->dbi_file, NULL); + oflags |= MDB_DUPSORT; + } - if (rpmxdbIsRdonly(lmdbenv->xdb)) - dbi->dbi_flags |= DBI_RDONLY; + MDB_txn * parent = NULL; + int tflags = ( +#ifdef REF + MDB_RDONLY | + MDB_NOSYNC | + MDB_NOMETASYNC | +#endif + 0 + ); + MDB_txn * txn = NULL; + rc = mdb_txn_begin(env, parent, tflags, &txn); + switch (rc) { + case MDB_SUCCESS: + rc = RPMRC_OK; + break; + case MDB_PANIC: + case MDB_MAP_RESIZED: + case MDB_READERS_FULL: + case ENOMEM: + default: + rc = RPMRC_FAIL; + break; + } + if (rc) + return rc; + + rc = mdb_dbi_open(txn, path, oflags, &lmdbdbi->dbi); + switch (rc) { + case MDB_SUCCESS: + rc = RPMRC_OK; + break; + case MDB_NOTFOUND: + case MDB_DBS_FULL: + default: + rc = RPMRC_FAIL; + break; } + if (rc) + return rc; if (dbip != NULL) *dbip = dbi; else lmdb_Close(dbi, 0); - return 0; + return rc; } static int lmdb_Verify(dbiIndex dbi, unsigned int flags) @@ -559,56 +489,8 @@ { } -static int indexSync(rpmpkgdb pkgdb, rpmxdb xdb) -{ - int rc = 0; - if (!pkgdb || !xdb) - return 1; - unsigned int generation = 0; - if (rpmpkgLock(pkgdb, 1)) - return 1; - if (rpmpkgGeneration(pkgdb, &generation)) { - rpmpkgUnlock(pkgdb, 1); - return 1; - } - rc = rpmxdbSetUserGeneration(xdb, generation); - rpmpkgUnlock(pkgdb, 1); - return rc; -} - static int lmdb_Ctrl(rpmdb rdb, dbCtrlOp ctrl) { - struct lmdbEnv_s *lmdbenv = rdb->db_dbenv; - - switch (ctrl) { - case DB_CTRL_LOCK_RO: - if (!rdb->db_pkgs) - return 1; - return rpmpkgLock(rdb->db_pkgs->dbi_db, 0); - break; - case DB_CTRL_LOCK_RW: - if (!rdb->db_pkgs) - return 1; - return rpmpkgLock(rdb->db_pkgs->dbi_db, 1); - break; - case DB_CTRL_UNLOCK_RO: - if (!rdb->db_pkgs) - return 1; - return rpmpkgUnlock(rdb->db_pkgs->dbi_db, 0); - break; - case DB_CTRL_UNLOCK_RW: - if (!rdb->db_pkgs) - return 1; - return rpmpkgUnlock(rdb->db_pkgs->dbi_db, 1); - break; - case DB_CTRL_INDEXSYNC: - if (!lmdbenv) - return 1; - return indexSync(lmdbenv->pkgdb, lmdbenv->xdb); - break; - default: - break; - } return 0; } @@ -622,53 +504,101 @@ static dbiCursor lmdb_CursorFree(dbiIndex dbi, dbiCursor dbc) { - if (dbc) { - if (dbc->list) - free(dbc->list); - if (dbc->listdata) - free(dbc->listdata); + if (dbc) free(dbc); - } return NULL; } - -static void setdata(dbiCursor dbc, unsigned int hdrNum, unsigned char *hdrBlob, unsigned int hdrLen) -{ - struct lmdbEnv_s *lmdbenv = dbc->dbi->dbi_rpmdb->db_dbenv; - if (lmdbenv->data) - free(lmdbenv->data); - lmdbenv->hdrNum = hdrNum; - lmdbenv->data = hdrBlob; - lmdbenv->datalen = hdrLen; -} - -static rpmRC lmdb_pkgdbNew(dbiIndex dbi, dbiCursor dbc, unsigned int *hdrNum) -{ - int rc = RPMRC_FAIL; - rc = rpmpkgNextPkgIdx(dbc->dbi->dbi_db, hdrNum); - if (!rc) - setdata(dbc, *hdrNum, 0, 0); - return rc; -} - static rpmRC lmdb_pkgdbPut(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char *hdrBlob, unsigned int hdrLen) { int rc = RPMRC_FAIL; - rc = rpmpkgPut(dbc->dbi->dbi_db, hdrNum, hdrBlob, hdrLen); - if (!rc) { - dbc->hdrNum = hdrNum; - setdata(dbc, hdrNum, 0, 0); + MDB_cursor * cursor = dbc->cursor; + + MDB_val key, data; + key.mv_size = sizeof(hdrNum); + key.mv_data = &hdrNum; + data.mv_size = hdrLen; + data.mv_data = hdrBlob; + + int flags = ( +#ifdef REF + MDB_CURRENT | + MDB_NODUPDATA | + MDB_NOOVERWRITE | + MDB_RESERVE | + MDB_APPEND | + MDB_APPENDDUP | + MDB_MULTIPLE | +#endif + 0 + ); + + flags |= MDB_APPEND; + rc = mdb_cursor_put(cursor, &key, &data, flags); + switch (rc) { + case MDB_SUCCESS: + rc = RPMRC_OK; + break; + case MDB_MAP_FULL: + case MDB_TXN_FULL: + case EACCES: + case EINVAL: + default: + rc = RPMRC_FAIL; + break; } + return rc; } static rpmRC lmdb_pkgdbDel(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum) { int rc = RPMRC_FAIL; - dbc->hdrNum = 0; - setdata(dbc, 0, 0, 0); - rc = rpmpkgDel(dbc->dbi->dbi_db, hdrNum); + MDB_cursor * cursor = dbc->cursor; + + MDB_val key, data; + key.mv_size = sizeof(hdrNum); + key.mv_data = &hdrNum; + data.mv_size = 0; + data.mv_data = NULL; + + MDB_cursor_op op = MDB_SET; + + rc = mdb_cursor_get(cursor, &key, &data, op); + switch (rc) { + case MDB_SUCCESS: + rc = RPMRC_OK; + break; + case MDB_NOTFOUND: + rc = RPMRC_NOTFOUND; + break; + case EINVAL: + default: + rc = RPMRC_FAIL; + break; + } + + if (!rc) { + unsigned int flags = ( +#ifdef REF + MDB_NODUPDATA | +#endif + 0 + ); + + rc = mdb_cursor_del(cursor, flags); + switch (rc) { + case MDB_SUCCESS: + rc = RPMRC_OK; + break; + case EACCES: + case EINVAL: + default: + rc = RPMRC_FAIL; + break; + } + } + return rc; } @@ -676,6 +606,8 @@ 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) { @@ -691,42 +623,57 @@ } *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++; - if (!rc) { - dbc->hdrNum = hdrNum; - setdata(dbc, hdrNum, *hdrBlob, *hdrLen); - break; - } } +#endif + return rc; } static rpmRC lmdb_pkgdbGet(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char **hdrBlob, unsigned int *hdrLen) { int rc = RPMRC_FAIL; - struct lmdbEnv_s *lmdbenv = dbc->dbi->dbi_rpmdb->db_dbenv; - if (!hdrNum) - return lmdb_pkgdbIter(dbi, dbc, hdrBlob, hdrLen); - if (hdrNum == lmdbenv->hdrNum && lmdbenv->data) { - *hdrBlob = lmdbenv->data; - *hdrLen = lmdbenv->datalen; - return RPMRC_OK; - } - rc = rpmpkgGet(dbc->dbi->dbi_db, hdrNum, hdrBlob, hdrLen); - if (!rc) { - dbc->hdrNum = hdrNum; - setdata(dbc, hdrNum, *hdrBlob, *hdrLen); + MDB_cursor * cursor = dbc->cursor; + + MDB_val key, data; + key.mv_size = sizeof(hdrNum); + key.mv_data = &hdrNum; + data.mv_size = 0; + data.mv_data = 0; + + MDB_cursor_op op = (hdrNum ? MDB_SET : MDB_NEXT); + + rc = mdb_cursor_get(cursor, &key, &data, op); + switch (rc) { + case MDB_SUCCESS: + dbc->key = key.mv_data; + dbc->keylen = key.mv_size; + if (hdrBlob) + *hdrBlob = data.mv_data; + if (hdrLen) + *hdrLen = data.mv_size; + rc = RPMRC_OK; + break; + case MDB_NOTFOUND: + dbc->key = NULL; + dbc->keylen = 0; + rc = RPMRC_NOTFOUND; + break; + case EINVAL: + default: + dbc->key = NULL; + dbc->keylen = 0; + rc = RPMRC_FAIL; + break; } - return rc; -} -static unsigned int lmdb_pkgdbKey(dbiIndex dbi, dbiCursor dbc) -{ - return dbc->hdrNum; + return rc; } @@ -743,10 +690,8 @@ if (pkglist) free(pkglist); if (*set) { -#ifdef NOTYET dbiIndexSetAppendSet(*set, newset, 0); dbiIndexSetFree(newset); -#endif } else *set = newset; } @@ -755,6 +700,8 @@ static rpmRC lmdb_idxdbIter(dbiIndex dbi, dbiCursor dbc, dbiIndexSet *set) { int 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); @@ -796,6 +743,8 @@ if (pkglist) free(pkglist); } +#endif + return rc; } @@ -859,7 +808,84 @@ return dbc->key; } +static unsigned int lmdb_pkgdbKey(dbiIndex dbi, dbiCursor dbc) +{ + if (dbc == NULL || dbc->key == NULL) + return 0; + unsigned int hdrNum = 0; + memcpy(&hdrNum, dbc->key, sizeof(hdrNum)); + return hdrNum; /* XXX byteswap */ +} + +static unsigned int pkgInstance(dbiIndex dbi, int alloc) +{ + unsigned int hdrNum = 0; + +#ifdef FIXME + if (dbi != NULL && dbi->dbi_type == DBI_PRIMARY) { + dbiCursor dbc; + DBT key, data; + unsigned int firstkey = 0; + union _dbswap mi_offset; + int ret; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + dbc = dbiCursorInit(dbi, alloc ? DBC_WRITE : 0); + + /* Key 0 holds the current largest instance, fetch it */ + key.data = &firstkey; + key.size = sizeof(firstkey); + ret = dbiCursorGet(dbc, &key, &data, DB_SET); + + if (ret == 0 && data.data) { + memcpy(&mi_offset, data.data, sizeof(mi_offset.ui)); + if (dbiByteSwapped(dbi) == 1) + _DBSWAP(mi_offset); + hdrNum = mi_offset.ui; + } + + if (alloc) { + /* Rather complicated "increment by one", bswapping as needed */ + ++hdrNum; + mi_offset.ui = hdrNum; + if (dbiByteSwapped(dbi) == 1) + _DBSWAP(mi_offset); + if (ret == 0 && data.data) { + memcpy(data.data, &mi_offset, sizeof(mi_offset.ui)); + } else { + data.data = &mi_offset; + data.size = sizeof(mi_offset.ui); + } + + /* Unless we manage to insert the new instance number, we failed */ + ret = dbiCursorPut(dbc, &key, &data, DB_KEYLAST); + if (ret) { + hdrNum = 0; + rpmlog(RPMLOG_ERR, + _("error(%d) allocating new package instance\n"), ret); + } + } + dbiCursorFree(dbi, dbc); + } +#endif + + return hdrNum; +} + +static rpmRC lmdb_pkgdbNew(dbiIndex dbi, dbiCursor dbc, unsigned int *hdrNum) +{ + unsigned int num = 0; + if (dbc == NULL) + return RPMRC_FAIL; + num = pkgInstance(dbc->dbi, 1); + if (!num) + return RPMRC_FAIL; + *hdrNum = num; + return RPMRC_OK; +} struct rpmdbOps_s lmdb_dbops = { .open = lmdb_Open, @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org