#include #include #include #include "db.h" // refer: https://docs.oracle.com/cd/E17076_05/html/gsg/C/BerkeleyDB-Core-C-GSG.pdf // Access Methods: // 1. BTree // 2. Hash // 3. Queue // 4. Recno // Use secondary database work as index. // Any attemp to write to a secondary database results in a non-zero status return. static int idx_callback(DB *dbp, const DBT *keyp, const DBT *valuep, DBT *resvp); #define USE_ENV 0 #define DESCRIPTION_SIZE 128 float money = 122.45; char *description = "Grocery bill."; typedef struct { int id; char *family_name; char *surname; } SPersion; static void put_value(DB *dbp) { DBT key = {0}; DBT value = {0}; int ret; key.data = &money; key.size = sizeof(money); value.data = description; value.size = strlen(description) + 1; ret = dbp->put(dbp, NULL, &key, &value, DB_NOOVERWRITE); if (ret != 0) { fprintf(stderr, "Failed to put DB record: %s\n", db_strerror(ret)); } } static void get_value(DB *dbp) { char desp[DESCRIPTION_SIZE]; DBT key = {0}; DBT value = {0}; key.data = &money; key.size = sizeof(money); value.data = desp; value.ulen = DESCRIPTION_SIZE; value.flags = DB_DBT_USERMEM; dbp->get(dbp, NULL, &key, &value, 0); printf("The value is \"%s\"\n", desp); } int main(int argc, char const *argv[]) { DB * dbp = NULL; DB * sdbp = NULL; u_int32_t db_flags; DB_ENV * envp = NULL; u_int32_t env_flags; int ret; DBT key = {0}; DBT value = {0}; #if USE_ENV // Initialize an env object and open it for ret = db_env_create(&envp, 0); if (ret != 0) { fprintf(stderr, "Error creating env handle: %s\n", db_strerror(ret)); return -1; } env_flags = DB_CREATE | DB_INIT_MPOOL; ret = envp->open(envp, "./meta", env_flags, 0); if (ret != 0) { fprintf(stderr, "Error opening env handle: %s\n", db_strerror(ret)); return -1; } #endif // Initialize a DB handle and open the DB ret = db_create(&dbp, envp, 0); if (ret != 0) { exit(1); } ret = db_create(&sdbp, envp, 0); if (ret != 0) { exit(1); } ret = sdbp->set_flags(sdbp, DB_DUPSORT); if (ret != 0) { exit(1); } db_flags = DB_CREATE | DB_TRUNCATE; ret = dbp->open(dbp, /* DB structure pointer */ NULL, /* Transaction pointer */ "meta.db", /* On-disk file that holds the database */ NULL, /* Optional logical database name */ DB_BTREE, /* Database access method */ db_flags, /* Open flags */ 0); /* File mode */ if (ret != 0) { exit(1); } ret = sdbp->open(sdbp, /* DB structure pointer */ NULL, /* Transaction pointer */ "index.db", /* On-disk file that holds the database */ NULL, /* Optional logical database name */ DB_BTREE, /* Database access method */ db_flags, /* Open flags */ 0); /* File mode */ if (ret != 0) { exit(1); } // Associate the secondary database to the primary dbp->associate(dbp, /* Primary database */ NULL, /* TXN id */ sdbp, /* Secondary database */ idx_callback, /* Callback used for key creation */ 0); /* Flags */ { // Insert a key-value record put_value(dbp); // Read the key-value record get_value(dbp); } // Close the database if (sdbp != NULL) { sdbp->close(sdbp, 0); } if (dbp != NULL) { dbp->close(dbp, 0); } if (envp != NULL) { envp->close(envp, 0); } return 0; } static int idx_callback(DB * sdbp, /* secondary db handle */ const DBT *keyp, /* primary db record's key */ const DBT *valuep, /* primary db record's value */ DBT * skeyp /* secondary db record's key*/ ) { DBT *tmpdbt; tmpdbt = (DBT *)calloc(2, sizeof(DBT)); { // TODO tmpdbt[0].data = NULL; tmpdbt[0].size = 0; tmpdbt[1].data = NULL; tmpdbt[1].size = 0; } /** * DB_DBT_MULTIPLE means DBT references an array * DB_DBT_APPMALLOC means we dynamically allocated memory for the DBT's data field. */ skeyp->flags = DB_DBT_MULTIPLE | DB_DBT_APPMALLOC; skeyp->size = 2; skeyp->data = tmpdbt; return 0; }