SPECS/libsolv/libsolv-lmdb.patch
2d24f0be
 diff --git a/CMakeLists.txt b/CMakeLists.txt
 index 605ab76..7fad325 100644
 --- a/CMakeLists.txt
 +++ b/CMakeLists.txt
 @@ -12,6 +12,7 @@ OPTION (ENABLE_TCL "Build the Tcl bindings?" OFF)
  
  OPTION (USE_VENDORDIRS "Install the bindings in vendor directories?" OFF)
  
 +OPTION (ENABLE_RPMDB_LMDB "Build with rpm db as lmdb?" OFF)
  OPTION (ENABLE_RPMDB "Build with rpm database support?" OFF)
  OPTION (ENABLE_RPMPKG "Build with rpm package support?" OFF)
  OPTION (ENABLE_PUBKEY "Build with pubkey support?" OFF)
 @@ -83,6 +84,17 @@ INCLUDE (${CMAKE_SOURCE_DIR}/VERSION.cmake)
  
  SET (have_system x)
  
 +IF (PHOTON)
 +MESSAGE(STATUS "Building for Photon")
 +ADD_DEFINITIONS (-DPHOTON)
 +SET (RPM5 ON)
 +SET (ENABLE_RPMDB ON)
 +SET (ENABLE_RPMMD ON)
 +SET (ENABLE_RPMDB_LMDB ON)
 +SET (ENABLE_COMPLEX_DEPS ON)
 +SET (have_system ${have_system}x)
 +ENDIF (PHOTON)
 +
  IF (FEDORA)
  MESSAGE(STATUS "Building for Fedora")
  ADD_DEFINITIONS (-DFEDORA)
 @@ -220,17 +232,25 @@ IF (ENABLE_RPMDB)
      ENDIF (RPMMISC_LIBRARY)
    ENDIF (RPM5)
  
 -  # check if rpm contains a bundled berkeley db
 -  CHECK_INCLUDE_FILE(rpm/db.h HAVE_RPM_DB_H)
 -  IF (NOT HAVE_RPM_DB_H)
 -    FIND_LIBRARY (DB_LIBRARY NAMES db)
 +  IF (NOT ENABLE_RPMDB_LMDB)
 +    # check if rpm contains a bundled berkeley db
 +    CHECK_INCLUDE_FILE(rpm/db.h HAVE_RPM_DB_H)
 +    IF (NOT HAVE_RPM_DB_H)
 +      FIND_LIBRARY (DB_LIBRARY NAMES db)
 +      IF (DB_LIBRARY)
 +        SET (RPMDB_LIBRARY ${DB_LIBRARY} ${RPMDB_LIBRARY})
 +      ENDIF (DB_LIBRARY)
 +      IF (DB_INCLUDE_DIR)
 +        INCLUDE_DIRECTORIES (${DB_INCLUDE_DIR})
 +      ENDIF (DB_INCLUDE_DIR)
 +    ENDIF (NOT HAVE_RPM_DB_H)
 +  ELSE (NOT ENABLE_RPMDB_LMDB)
 +    FIND_LIBRARY (DB_LIBRARY NAMES lmdb)
      IF (DB_LIBRARY)
        SET (RPMDB_LIBRARY ${DB_LIBRARY} ${RPMDB_LIBRARY})
      ENDIF (DB_LIBRARY)
 -    IF (DB_INCLUDE_DIR)
 -      INCLUDE_DIRECTORIES (${DB_INCLUDE_DIR})
 -    ENDIF (DB_INCLUDE_DIR)
 -  ENDIF (NOT HAVE_RPM_DB_H)
 +  ENDIF (NOT ENABLE_RPMDB_LMDB)
 +
    INCLUDE (CheckLibraryExists)
    CHECK_LIBRARY_EXISTS(rpmio pgpDigGetParams "" HAVE_PGPDIGGETPARAMS)
  ENDIF (ENABLE_RPMDB)
 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
 index 703796c..d56184f 100644
 --- a/examples/CMakeLists.txt
 +++ b/examples/CMakeLists.txt
 @@ -1,5 +1,5 @@
 -IF (SUSE OR FEDORA OR DEBIAN OR MANDRIVA OR MAGEIA)
 +IF (PHOTON OR SUSE OR FEDORA OR DEBIAN OR MANDRIVA OR MAGEIA)
  
  ADD_SUBDIRECTORY (solv)
  
 -ENDIF (SUSE OR FEDORA OR DEBIAN OR MANDRIVA OR MAGEIA)
 +ENDIF (PHOTON OR SUSE OR FEDORA OR DEBIAN OR MANDRIVA OR MAGEIA)
 diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt
 index b8917a2..5d75c3f 100644
 --- a/ext/CMakeLists.txt
 +++ b/ext/CMakeLists.txt
 @@ -11,6 +11,13 @@ IF (ENABLE_RPMDB OR ENABLE_RPMPKG)
          pool_fileconflicts.h repo_rpmdb.h)
  ENDIF (ENABLE_RPMDB OR ENABLE_RPMPKG)
  
 +IF (ENABLE_RPMDB_LMDB)
 +    SET (libsolvext_SRCS ${libsolvext_SRCS}
 +        db_lmdb.c)
 +    SET (libsolvext_HEADERS ${libsolvext_HEADERS}
 +        db_lmdb.h)
 +ENDIF (ENABLE_RPMDB_LMDB)
 +
  IF (ENABLE_PUBKEY)
      SET (libsolvext_SRCS ${libsolvext_SRCS}
  	repo_pubkey.c)
 diff --git a/ext/db_lmdb.c b/ext/db_lmdb.c
 new file mode 100644
 index 0000000..c3941b0
 --- /dev/null
 +++ b/ext/db_lmdb.c
 @@ -0,0 +1,258 @@
 +/*
 + * Copyright (c) 2007-2012, Novell Inc.
 + *
 + * This program is licensed under the BSD license, read LICENSE.BSD
 + * for further information
 + */
 +
 +/*
 + * db_lmdb
 + *
 + * bridge for db to lmdb calls
 + *
 + */
 +
 +#include <sys/types.h>
 +#include <sys/stat.h>
 +#include <limits.h>
 +#include <fcntl.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <unistd.h>
 +#include <assert.h>
 +#include <stdint.h>
 +#include <errno.h>
 +
 +#include "db_lmdb.h"
 +#include "util.h"
 +
 +int db_env_open(struct _DB_ENV_ *dbenv, const char *dbpath, u_int32_t flags, int naccess)
 +{
 +  int err = 0;
 +
 +  err = mdb_env_open(dbenv->env, dbpath, 0, naccess);
 +  bail_on_error(err);
 +
 +error:
 +  return err;  
 +}
 +
 +int db_env_close(struct _DB_ENV_ *dbenv, u_int32_t flags)
 +{
 +  int err = 0;
 +
 +  if(dbenv && dbenv->env)
 +    mdb_env_close(dbenv->env);
 +
 +  return err;
 +}
 +
 +int db_env_get_open_flags(struct _DB_ENV_ *dbenv, u_int32_t *flags)
 +{
 +  *flags = 0;
 +  return 0;
 +}
 +
 +int db_env_create (DB_ENV **dbenvp, u_int32_t flags)
 +{
 +  DB_ENV *dbenv = NULL;
 +  MDB_env *mdbenv = NULL;
 +  int err = 0;
 +
 +  dbenv = solv_malloc(sizeof(DB_ENV));
 +  if(!dbenv)
 +    err = ENOMEM;
 +  bail_on_error(err);
 +
 +  err = mdb_env_create(&mdbenv);
 +  bail_on_error(err);
 +
 +  err = mdb_env_set_maxreaders(mdbenv, 16);
 +  bail_on_error(err);
 +
 +  err = mdb_env_set_maxdbs(mdbenv, 32);
 +  bail_on_error(err);
 +
 +  err = mdb_env_set_mapsize(mdbenv, 50*1024*1024);
 +  bail_on_error(err);
 +
 +  dbenv->env = mdbenv;
 +  dbenv->open = db_env_open;
 +  dbenv->close = db_env_close;
 +  dbenv->get_open_flags = db_env_get_open_flags;
 +
 +  *dbenvp = dbenv;
 +cleanup:
 +  return err;
 +
 +error:
 +  if(mdbenv)
 +    mdb_env_close(mdbenv);
 +  solv_free(dbenv);
 +  goto cleanup;
 +}
 +
 +//db
 +int db_close(struct _DB_ *db, u_int32_t flags)
 +{
 +  return 0;
 +}
 +
 +int dbc_close(struct _DBC_ *dbc)
 +{
 +/*
 +  if(dbc->txn)
 +  {
 +    if(dbc->txn->txn)
 +      mdb_txn_abort(dbc->txn->txn);
 +    dbc->txn->txn = NULL;
 +    solv_free(dbc->txn);
 +  }
 +  dbc->txn = NULL;
 +*/
 +  return 0;
 +}
 +
 +int dbc_c_close(struct _DBC_ *dbc)
 +{
 +  if(dbc->cursor)
 +    mdb_cursor_close(dbc->cursor);
 +  dbc->cursor = NULL;
 +  return 0;
 +}
 +
 +int dbc_c_get(struct _DBC_ *dbc, struct _DBT_ *key, struct _DBT_ *value, u_int32_t flags)
 +{
 +  int err = 0;
 +  u_int32_t flagsin = flags == DB_SET ? MDB_SET : MDB_NEXT;
 +  MDB_val mkey, mval;
 +
 +  if(flagsin == MDB_SET)
 +  {
 +    mkey.mv_size = key->size;
 +    mkey.mv_data = key->data;
 +  }
 +
 +  err = mdb_cursor_get(dbc->cursor, &mkey, &mval, flagsin);
 +  bail_on_error(err);
 +
 +  if(flagsin == MDB_NEXT)
 +  {
 +    key->size = mkey.mv_size;
 +    key->data = mkey.mv_data;
 +  }
 +  value->size = mval.mv_size;
 +  value->data = mval.mv_data;
 +
 +cleanup:
 +  return err;
 +error:
 +  goto cleanup;
 +}
 +
 +int db_cursor(struct _DB_ *db, struct _DB_TXN_ *txn,
 +              struct _DBC_ **dbcp, u_int32_t flags)
 +{
 +  int err = 0;
 +  DBC *dbc = NULL;
 +
 +  DB_TXN *txncurrent = txn ? txn : db->txn;
 +
 +  if(!txncurrent || !txncurrent->txn)
 +    err = EINVAL;
 +  bail_on_error(err);
 +
 +  dbc = solv_malloc(sizeof(DBC));
 +  if(!dbc)
 +    err = ENOMEM;    
 +  bail_on_error(err);
 +
 +  err = mdb_cursor_open(txncurrent->txn, db->db, &dbc->cursor);
 +  bail_on_error(err);
 +
 +  dbc->close = dbc_close;
 +  dbc->c_close = dbc_c_close;
 +  dbc->c_get = dbc_c_get;
 +
 +  *dbcp = dbc;
 +cleanup:
 +  return err;
 +error:
 +  solv_free(dbc);
 +  goto cleanup;
 +}
 + 
 +int db_get(struct _DB_ *db, struct _DB_TXN_ *txn,
 +           struct _DBT_ *key, struct _DBT_ *value, u_int32_t flags)
 +{
 +  return 0;
 +}
 +
 +int db_open(struct _DB_ *db, struct _DB_TXN_ *txn,
 +            const char *file, const char *database,
 +            DBTYPE dbtype, u_int32_t flags, int mode)
 +{
 +  int err = 0;
 +  DB_TXN *txnp = NULL;
 +  MDB_dbi dbi = -1;
 +  DB_TXN *txncurrent = txn;
 +
 +  if(!txn)
 +  {
 +    u_int32_t txnflags = flags & DB_RDONLY ? MDB_RDONLY : 0;
 +    txnp = solv_malloc(sizeof(DB_TXN));
 +    if(!txnp)
 +      err = ENOMEM;    
 +    bail_on_error(err);
 +
 +    err = mdb_txn_begin(db->env, NULL, txnflags, &txnp->txn);
 +    bail_on_error(err);
 +
 +    txncurrent = txnp;
 +  }
 +
 +  err = mdb_dbi_open(txncurrent->txn, file, 0, &dbi);
 +  bail_on_error(err);
 +  
 +  db->txn = txnp;
 +  db->db = dbi;
 +
 +cleanup:
 +  return err;
 +error:
 +  solv_free(txnp);
 +  goto cleanup;
 +}
 +
 +int db_get_byteswapped(struct _DB_ *db, int *byteswapped)
 +{
 +  *byteswapped = 0;
 +  return 0;
 +}
 +
 +int db_create (DB **db, DB_ENV *dbenv, u_int32_t flags)
 +{
 +  int err = 0;
 +  DB *dbp = NULL;
 +
 +  dbp = solv_malloc(sizeof(DB));
 +  if(!dbp)
 +    err = ENOMEM;
 +  bail_on_error(err);
 +
 +
 +  dbp->env = dbenv->env;
 +  dbp->close = db_close;
 +  dbp->cursor = db_cursor;
 +  dbp->get = db_get;
 +  dbp->get_byteswapped = db_get_byteswapped;
 +  dbp->open = db_open;
 +  *db = dbp;
 +
 +cleanup:
 +  return err;
 +error:
 +  solv_free(dbp);
 +  goto cleanup;
 +}
 diff --git a/ext/db_lmdb.h b/ext/db_lmdb.h
 new file mode 100644
 index 0000000..4eb197d
 --- /dev/null
 +++ b/ext/db_lmdb.h
 @@ -0,0 +1,83 @@
 +/*
 + * Copyright (c) 2007-2008, Novell Inc.
 + *
 + * This program is licensed under the BSD license, read LICENSE.BSD
 + * for further information
 + */
 +
 +#ifndef RPM_LMDB_H
 +#define RPM_LMDB_H
 +
 +#include <lmdb.h>
 +
 +typedef enum
 +{
 +  DB_UNKNOWN=5
 +} DBTYPE;
 +
 +typedef struct _DB_ENV_
 +{
 +  MDB_env *env;
 +  int  (*get_open_flags) (struct _DB_ENV_ *, u_int32_t *);
 +  int  (*open) (struct _DB_ENV_ *, const char *, u_int32_t, int);
 +  int  (*close) (struct _DB_ENV_ *, u_int32_t);
 +}DB_ENV;
 +
 +typedef struct _DB_TXN_
 +{
 +  MDB_txn *txn;
 +}DB_TXN;
 +
 +typedef struct _DBT_
 +{
 +  void *data;
 +  u_int32_t size;
 +}DBT;
 +
 +typedef struct _DBC_
 +{
 +  MDB_cursor *cursor;
 +  int (*close) (struct _DBC_ *);
 +  int (*c_close) (struct _DBC_ *);
 +  int (*c_get) (struct _DBC_ *, struct _DBT_ *, struct _DBT_ *, u_int32_t);
 +}DBC;
 +
 +typedef struct _DB_
 +{
 +  DB_TXN *txn;
 +  MDB_dbi db;
 +  MDB_env *env;
 +  int  (*close) (struct _DB_ *, u_int32_t);
 +  int  (*cursor)(struct _DB_ *, struct _DB_TXN_ *, struct _DBC_ **, u_int32_t);
 +  int  (*get) (struct _DB_ *, struct _DB_TXN_ *, struct _DBT_ *, struct _DBT_ *, u_int32_t);
 +  int  (*get_byteswapped) (struct _DB_ *, int *);
 +  int  (*open) (struct _DB_ *,
 +                  struct _DB_TXN_ *,
 +                  const char *,
 +                  const char *,
 +                  DBTYPE,
 +                  u_int32_t,
 +                  int);
 +}DB;
 +
 +//definitions from db.h
 +#define	DB_CREATE     0x00000001
 +#define	DB_INIT_CDB   0x00000080
 +#define	DB_INIT_MPOOL 0x00000400
 +#define	DB_PRIVATE    0x00010000
 +#define	DB_RDONLY     0x00000400
 +
 +#define	DB_NEXT       16
 +#define	DB_SET        26
 +
 +int db_env_create (DB_ENV **, u_int32_t);
 +int db_create (DB **, DB_ENV *, u_int32_t);
 +
 +#define bail_on_error(nerror) \
 +    do {                                                           \
 +        if (nerror)                                               \
 +        {                                                          \
 +            goto error;                                            \
 +        }                                                          \
 +    } while(0)
 +#endif//RPM_LMDB_H
 diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c
 index fe05bec..9f4ad31 100644
 --- a/ext/repo_rpmdb.c
 +++ b/ext/repo_rpmdb.c
 @@ -25,6 +25,7 @@
  #include <errno.h>
  
  #ifdef ENABLE_RPMDB
 +#define ENABLE_RPMDB_LMDB
  
  #include <rpm/rpmio.h>
  #include <rpm/rpmpgp.h>
 @@ -37,7 +38,11 @@
  # if defined(SUSE) || defined(HAVE_RPM_DB_H)
  #  include <rpm/db.h>
  # else
 -#  include <db.h>
 +#  ifdef ENABLE_RPMDB_LMDB
 +#   include "db_lmdb.h"
 +#  else
 +#   include <db.h>
 +#  endif
  # endif
  #endif
  
 @@ -1515,7 +1520,7 @@ count_headers(struct rpmdbstate *state)
    DBT dbkey;
    DBT dbdata;
  
 -  snprintf(dbpath, PATH_MAX, "%s%s/Name", state->rootdir ? state->rootdir : "", state->is_ostree ? "/usr/share/rpm" : "/var/lib/rpm");
 +  snprintf(dbpath, PATH_MAX, "%s%s/data.mdb", state->rootdir ? state->rootdir : "", state->is_ostree ? "/usr/share/rpm" : "/var/lib/rpm");
    if (stat(dbpath, &statbuf))
      return 0;
    memset(&dbkey, 0, sizeof(dbkey));
 @@ -1841,7 +1846,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags)
      }
  
    /* XXX: should get ro lock of Packages database! */
 -  snprintf(dbpath, PATH_MAX, "%s%s/Packages", state.rootdir ? state.rootdir : "", state.is_ostree ? "/usr/share/rpm" : "/var/lib/rpm");
 +  snprintf(dbpath, PATH_MAX, "%s%s/data.mdb", state.rootdir ? state.rootdir : "", state.is_ostree ? "/usr/share/rpm" : "/var/lib/rpm");
    if (stat(dbpath, &packagesstat))
      {
        pool_error(pool, -1, "%s: %s", dbpath, strerror(errno));