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 16:19:33 Branch: rpm-5_4 Handle: 2017072214193300 Modified files: (Branch: rpm-5_4) rpm/rpmdb Makefile.am lmdb.c Log: - lmdb: stub-in the rpm.org lib/backend/ndb/glue.c layer. Summary: Revision Changes Path 1.134.2.38 +6 -0 rpm/rpmdb/Makefile.am 1.1.2.2 +905 -6 rpm/rpmdb/lmdb.c ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/rpmdb/Makefile.am ============================================================================ $ cvs diff -u -r1.134.2.37 -r1.134.2.38 Makefile.am --- rpm/rpmdb/Makefile.am 21 Jul 2017 15:14:23 -0000 1.134.2.37 +++ rpm/rpmdb/Makefile.am 22 Jul 2017 14:19:33 -0000 1.134.2.38 @@ -329,9 +329,15 @@ logio_SOURCES = logio.c logio.h logio_LDADD = $(mylibs) +lmdb_CFLAGS = -I/X/src/rpm/include -I/X/src/rpm lmdb_SOURCES = lmdb.c lmdb_LDADD = $(mylibs) +ltest: lmdb + rm -rf testdb && mkdir testdb + ./lmdb + ls -al testdb + #libsqldb_la_SOURCES = libsqldb.c # sqlite.c #libsqldb_la_LIBADD = $(RPMIO_LDADD_COMMON) @@ . patch -p0 <<'@@ .' Index: rpm/rpmdb/lmdb.c ============================================================================ $ cvs diff -u -r1.1.2.1 -r1.1.2.2 lmdb.c --- rpm/rpmdb/lmdb.c 21 Jul 2017 15:14:23 -0000 1.1.2.1 +++ rpm/rpmdb/lmdb.c 22 Jul 2017 14:19:33 -0000 1.1.2.2 @@ -1,16 +1,909 @@ -#include <stdio.h> -#include <stdlib.h> -#include <time.h> +#include "system.h" + +#include <rpmio.h> +#include <rpmlog.h> +#include <argv.h> +#include <poptIO.h> + #include "lmdb.h" +#include "debug.h" + +static int _debug = -1; + #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) +/*==============================================================*/ + +#define H_RPMSW + +#define _RPMTYPES_H +typedef struct headerToken_s * Header; +typedef int32_t rpm_tag_t; +typedef uint32_t rpm_tagtype_t; +typedef uint32_t rpm_count_t; +typedef rpm_tag_t rpmTagVal; + +typedef struct rpmts_s * rpmts; +typedef void * rpmDbiTag; + +typedef rpm_tag_t rpmDbiTagVal; + +typedef struct dbiIndex_s * dbiIndex; +typedef struct dbiCursor_s * dbiCursor; +typedef struct dbiIndexSet_s * dbiIndexSet; + +typedef struct rpmdb_s * rpmdb; + +#ifdef REFERENCE +struct dbConfig_s { + int db_mmapsize; /*!< (10Mb) */ + int db_cachesize; /*!< (128Kb) */ + int db_verbose; + int db_no_fsync; /*!< no-op fsync for db */ + int db_eflags; /*!< obsolete */ +}; + +struct dbiConfig_s { + int dbi_oflags; /*!< open flags */ + int dbi_no_dbsync; /*!< don't call dbiSync */ + int dbi_lockdbfd; /*!< do fcntl lock on db fd */ +}; + +struct rpmdbOps_s; + +/** \ingroup rpmdb + * Describes the collection of index databases used by rpm. + */ +struct rpmdb_s { + char * db_root;/*!< path prefix */ + char * db_home;/*!< directory path */ + char * db_fullpath; /*!< full db path including prefix */ + int db_flags; + int db_mode; /*!< open mode */ + int db_perms; /*!< open permissions */ + char * db_descr; /*!< db backend description (for error msgs) */ + struct dbChk_s * db_checked;/*!< headerCheck()'ed package instances */ + rpmdb db_next; + int db_opens; + dbiIndex db_pkgs; /*!< Package db */ + const rpmDbiTag * db_tags; + int db_ndbi; /*!< No. of tag indices. */ + dbiIndex * db_indexes; /*!< Tag indices. */ + int db_buildindex; /*!< Index rebuild indicator */ + + struct rpmdbOps_s * db_ops; /*!< backend ops */ + + /* dbenv and related parameters */ + void * db_dbenv; /*!< Backend private handle */ + struct dbConfig_s cfg; + int db_remove_env; + + struct rpmop_s db_getops; + struct rpmop_s db_putops; + struct rpmop_s db_delops; + + int nrefs; /*!< Reference count. */ +}; +#endif /* REFERENCE */ + +typedef struct miRE_s * miRE; + +typedef struct rpmdbMatchIterator_s * rpmdbMatchIterator; +struct rpmdbMatchIterator_s { + rpmdbMatchIterator mi_next; + rpmdb mi_db; + rpmDbiTagVal mi_rpmtag; + dbiIndexSet mi_set; + dbiCursor mi_dbc; + int mi_setx; + Header mi_h; + int mi_sorted; + int mi_cflags; + int mi_modified; + unsigned int mi_prevoffset; /* header instance (native endian) */ + unsigned int mi_offset; /* header instance (native endian) */ + unsigned int mi_filenum; /* tag element (native endian) */ + int mi_nre; + miRE mi_re; + rpmts mi_ts; + rpmRC (*mi_hdrchk) (rpmts ts, const void * uh, size_t uc, char ** msg); +}; + +typedef struct rpmdbIndexIterator_s * rpmdbIndexIterator; +struct rpmdbIndexIterator_s { + rpmdbIndexIterator ii_next; + rpmdb ii_db; + dbiIndex ii_dbi; + rpmDbiTag ii_rpmtag; + dbiCursor ii_dbc; + dbiIndexSet ii_set; + unsigned int *ii_hdrNums; +}; + +#define _RPMUTIL_H + +#include "lib/rpmdb_internal.h" + +/*==============================================================*/ +RPM_GNUC_PURE +dbiIndex dbiFree(dbiIndex dbi) +{ + if (dbi) + free(dbi); + return NULL; +} + +#define RPMDBI_PACKAGES 0 +dbiIndex dbiNew(rpmdb rdb, rpmDbiTagVal rpmtag) +{ + dbiIndex dbi = xcalloc(1, sizeof(*dbi)); + dbi->dbi_rpmdb = rdb; +#ifdef NOTYET + dbi->dbi_file = rpmTagGetName(rpmtag); +#endif + dbi->dbi_type = (rpmtag == RPMDBI_PACKAGES) ? DBI_PRIMARY : DBI_SECONDARY; + dbi->dbi_byteswapped = -1; /* -1 unknown, 0 native order, 1 alien order */ + return dbi; +} + +RPM_GNUC_PURE +const char * dbiName(dbiIndex dbi) +{ + return dbi->dbi_file; +} + +RPM_GNUC_PURE +int dbiFlags(dbiIndex dbi) +{ + return dbi->dbi_flags; +} + +void dbiIndexSetGrow(dbiIndexSet set, unsigned int nrecs) +{ + size_t need = (set->count + nrecs) * sizeof(*(set->recs)); + size_t alloced = set->alloced ? set->alloced : 1 << 4; + + while (alloced < need) + alloced <<= 1; + + if (alloced != set->alloced) { + set->recs = xrealloc(set->recs, alloced); + set->alloced = alloced; + } +} + +dbiIndexSet dbiIndexSetNew(unsigned int sizehint) +{ + dbiIndexSet set = xcalloc(1, sizeof(*set)); + if (sizehint > 0) + dbiIndexSetGrow(set, sizehint); + return set; +} + +#define rpmChrootDone() (0) + +RPM_GNUC_PURE +const char *rpmdbHome(rpmdb db) +{ + const char *dbdir = NULL; + if (db) { + dbdir = rpmChrootDone() ? db->db_home : db->db_fullpath; + } + return dbdir; +} + +/*==============================================================*/ +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; +} + +/*==============================================================*/ +typedef struct rpmidxdb_s *rpmidxdb; + +RPM_GNUC_CONST +void rpmidxClose(rpmidxdb idxdb) +{ +} + +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; +} + +RPM_GNUC_CONST +int rpmidxPut(rpmidxdb idxdb, const unsigned char *key, unsigned int keyl, unsigned int pkgidx, unsigned int datidx) +{ + return RPMRC_FAIL; +} + +RPM_GNUC_CONST +int rpmidxDel(rpmidxdb idxdb, const unsigned char *key, unsigned int keyl, unsigned int pkgidx, unsigned int datidx) +{ + return RPMRC_FAIL; +} + +RPM_GNUC_CONST +int rpmidxList(rpmidxdb idxdb, unsigned int **keylistp, unsigned int *nkeylistp, unsigned char **datap) +{ + return RPMRC_FAIL; +} + +RPM_GNUC_CONST +int rpmidxOpenXdb(rpmidxdb *idxdbp, rpmpkgdb pkgdb, rpmxdb xdb, unsigned int xdbtag) +{ + return RPMRC_FAIL; +} + +/*==============================================================*/ + +struct dbiCursor_s { + dbiIndex dbi; + const void *key; + unsigned int keylen; + unsigned int hdrNum; + int flags; + + unsigned int *list; + unsigned int nlist; + unsigned int ilist; + unsigned char *listdata; +}; + +struct lmdbEnv_s { + rpmpkgdb pkgdb; + rpmxdb xdb; + 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); + free(lmdbenv); + rdb->db_dbenv = 0; + } +} + +static struct lmdbEnv_s *openEnv(rpmdb rdb) +{ + struct lmdbEnv_s *lmdbenv = rdb->db_dbenv; + if (!lmdbenv) + rdb->db_dbenv = lmdbenv = xcalloc(1, sizeof(struct lmdbEnv_s)); + lmdbenv->refs++; + return lmdbenv; +} + +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); + } + if (rdb->db_dbenv) + closeEnv(rdb); + dbi->dbi_db = 0; + 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) + *dbip = NULL; + + if ((dbi = dbiNew(rdb, rpmtag)) == NULL) + return 1; + + lmdbenv = openEnv(rdb); + + 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); + 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; + } 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; + + if (rpmxdbIsRdonly(lmdbenv->xdb)) + dbi->dbi_flags |= DBI_RDONLY; + } + + if (dbip != NULL) + *dbip = dbi; + else + lmdb_Close(dbi, 0); + + return 0; +} + +static int lmdb_Verify(dbiIndex dbi, unsigned int flags) +{ + return 1; +} + +static void lmdb_SetFSync(rpmdb rdb, int enable) +{ +} + +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; +} + +static dbiCursor lmdb_CursorInit(dbiIndex dbi, unsigned int flags) +{ + dbiCursor dbc = xcalloc(1, sizeof(*dbc)); + dbc->dbi = dbi; + dbc->flags = flags; + return dbc; +} + +static dbiCursor lmdb_CursorFree(dbiIndex dbi, dbiCursor dbc) +{ + if (dbc) { + if (dbc->list) + free(dbc->list); + if (dbc->listdata) + free(dbc->listdata); + 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); + } + 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); + return rc; +} + +/* iterate over all packages */ +static rpmRC lmdb_pkgdbIter(dbiIndex dbi, dbiCursor dbc, unsigned char **hdrBlob, unsigned int *hdrLen) +{ + int rc = RPMRC_FAIL; + 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]; + rc = rpmpkgGet(dbc->dbi->dbi_db, hdrNum, hdrBlob, hdrLen); + if (rc && rc != RPMRC_NOTFOUND) + break; + dbc->ilist++; + if (!rc) { + dbc->hdrNum = hdrNum; + setdata(dbc, hdrNum, *hdrBlob, *hdrLen); + break; + } + } + 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); + } + return rc; +} + +static unsigned int lmdb_pkgdbKey(dbiIndex dbi, dbiCursor dbc) +{ + return dbc->hdrNum; +} + + +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++; + } + newset->count = j; + if (pkglist) + free(pkglist); + if (*set) { +#ifdef NOTYET + dbiIndexSetAppendSet(*set, newset, 0); + dbiIndexSetFree(newset); +#endif + } else + *set = newset; +} + +/* Iterate over all index entries */ +static rpmRC lmdb_idxdbIter(dbiIndex dbi, dbiCursor dbc, dbiIndexSet *set) +{ + int rc = RPMRC_FAIL; + 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; + } + for (;;) { + unsigned char *k; + unsigned int kl; + unsigned int *pkglist, pkglistn; + if (dbc->ilist >= dbc->nlist) { + rc = RPMRC_NOTFOUND; + 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; + break; + } +#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; + break; + } + if (pkglist) + free(pkglist); + } + return rc; +} + +static rpmRC lmdb_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexSet *set, int searchType) +{ + int rc = RPMRC_FAIL; + unsigned int *pkglist = 0, pkglistn = 0; + + if (!keyp) + return lmdb_idxdbIter(dbi, dbc, set); + + 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) + return rc; + 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); + return rc ? rc : rrc; + } + + rc = rpmidxGet(dbc->dbi->dbi_db, (const unsigned char *)keyp, keylen, &pkglist, &pkglistn); + if (!rc) + addtoset(set, pkglist, pkglistn); + return rc; +} + +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); + 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); + return rc; +} + +static const void * lmdb_idxdbKey(dbiIndex dbi, dbiCursor dbc, unsigned int *keylen) +{ + if (dbc->key && keylen) + *keylen = dbc->keylen; + return dbc->key; +} + + + +struct rpmdbOps_s lmdb_dbops = { + .open = lmdb_Open, + .close = lmdb_Close, + .verify = lmdb_Verify, + .setFSync = lmdb_SetFSync, + .ctrl = lmdb_Ctrl, + + .cursorInit = lmdb_CursorInit, + .cursorFree = lmdb_CursorFree, + + .pkgdbNew = lmdb_pkgdbNew, + .pkgdbPut = lmdb_pkgdbPut, + .pkgdbDel = lmdb_pkgdbDel, + .pkgdbGet = lmdb_pkgdbGet, + .pkgdbKey = lmdb_pkgdbKey, + + .idxdbGet = lmdb_idxdbGet, + .idxdbPut = lmdb_idxdbPut, + .idxdbDel = lmdb_idxdbDel, + .idxdbKey = lmdb_idxdbKey +}; + + +/*==============================================================*/ +struct poptOption lmdbOptionsTable[] = { + { "debug", 'd', POPT_ARG_VAL, &_debug, -1, + NULL, NULL }, + + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmioAllPoptTable, 0, + N_("Common options for all rpmio executables:"), NULL }, + + POPT_AUTOALIAS + POPT_AUTOHELP + POPT_TABLEEND +}; + +struct rpmdb_s _rpmdb; +rpmdb rdb = &_rpmdb; + int main(int argc, char *argv[]) { - int i = 0, j = 0, rc; + poptContext con = rpmioInit(argc, argv, lmdbOptionsTable); + int ec = 0; MDB_env *env; MDB_dbi dbi; MDB_val key, data; @@ -21,11 +914,14 @@ int count; int *values; char sval[32] = ""; + int rc; + int i; + int j; srand(time(NULL)); count = (rand() % 384) + 64; - values = (int *) malloc(count * sizeof(int)); + values = (int *) xmalloc(count * sizeof(int)); for (i = 0; i < count; i++) values[i] = rand() % 1024; @@ -42,6 +938,7 @@ key.mv_data = sval; printf("Adding %d values\n", count); + j = 0; for (i = 0; i < count; i++) { sprintf(sval, "%03x %d foo bar", values[i], values[i]); /* Set <data> in each iteration, since MDB_NOOVERWRITE may modify it */ @@ -160,5 +1057,7 @@ mdb_dbi_close(env, dbi); mdb_env_close(env); - return 0; + con = rpmioFini(con); + + return ec; } @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org