diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2015-02-17 17:25:57 +0000 |
---|---|---|
committer | <> | 2015-03-17 16:26:24 +0000 |
commit | 780b92ada9afcf1d58085a83a0b9e6bc982203d1 (patch) | |
tree | 598f8b9fa431b228d29897e798de4ac0c1d3d970 /examples/c | |
parent | 7a2660ba9cc2dc03a69ddfcfd95369395cc87444 (diff) | |
download | berkeleydb-master.tar.gz |
Diffstat (limited to 'examples/c')
45 files changed, 851 insertions, 247 deletions
diff --git a/examples/c/csv/DbRecord.c b/examples/c/csv/DbRecord.c index b25aeadc..d3c975b4 100644 --- a/examples/c/csv/DbRecord.c +++ b/examples/c/csv/DbRecord.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/csv/README b/examples/c/csv/README index 6d5eb878..1da48a36 100644 --- a/examples/c/csv/README +++ b/examples/c/csv/README @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/csv/code.c b/examples/c/csv/code.c index 24aaac81..85c6c792 100644 --- a/examples/c/csv/code.c +++ b/examples/c/csv/code.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -26,7 +26,8 @@ int usage(void); * Globals */ FILE *cfp; /* C source file */ -FILE *hfp; /* C source file */ +FILE *ffp; /* CSV file */ +FILE *hfp; /* C header file */ char *progname; /* Program name */ int verbose; /* Verbose flag */ @@ -45,6 +46,8 @@ main(int argc, char *argv[]) else ++progname; + ffp = NULL; + /* Initialize arguments. */ cfile = "csv_local.c"; /* Default header/source files */ hfile = "csv_local.h"; @@ -55,8 +58,8 @@ main(int argc, char *argv[]) case 'c': cfile = optarg; break; - case 'f': - if (freopen(optarg, "r", stdin) == NULL) { + case 'f': /* Required argument */ + if ((ffp = freopen(optarg, "r", stdin)) == NULL) { fprintf(stderr, "%s: %s\n", optarg, strerror(errno)); return (EXIT_FAILURE); @@ -75,7 +78,7 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - if (*argv != NULL) + if (*argv != NULL || ffp == NULL) return (usage()); /* Load records from the input file. */ diff --git a/examples/c/csv/csv.h b/examples/c/csv/csv.h index ac9fac2a..beb67cbc 100644 --- a/examples/c/csv/csv.h +++ b/examples/c/csv/csv.h @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/csv/csv_extern.h b/examples/c/csv/csv_extern.h index a541bb5c..59b468f0 100644 --- a/examples/c/csv/csv_extern.h +++ b/examples/c/csv/csv_extern.h @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -17,9 +17,9 @@ extern void DbRecord_print(DbRecord *, FILE *); extern int DbRecord_read(u_long, DbRecord *); extern int DbRecord_search_field_name(char *, char *, OPERATOR); extern int DbRecord_search_field_number(u_int, char *, OPERATOR); -extern int compare_double(DB *, const DBT *, const DBT *); -extern int compare_string(DB *, const DBT *, const DBT *); -extern int compare_ulong(DB *, const DBT *, const DBT *); +extern int compare_double(DB *, const DBT *, const DBT *, size_t *); +extern int compare_string(DB *, const DBT *, const DBT *, size_t *); +extern int compare_ulong(DB *, const DBT *, const DBT *, size_t *); extern int csv_env_close(void); extern int csv_env_open(const char *, int); extern int csv_secondary_close(void); diff --git a/examples/c/csv/db.c b/examples/c/csv/db.c index dc72f0d8..e138d5b8 100644 --- a/examples/c/csv/db.c +++ b/examples/c/csv/db.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -10,7 +10,7 @@ #include "csv_local.h" #include "csv_extern.h" -static int compare_uint32(DB *, const DBT *, const DBT *); +static int compare_uint32(DB *, const DBT *, const DBT *, size_t *); /* * csv_env_init -- @@ -138,7 +138,7 @@ csv_secondary_open() { DB *sdb; DbField *f; - int ret, (*fcmp)(DB *, const DBT *, const DBT *); + int ret, (*fcmp)(DB *, const DBT *, const DBT *, size_t *); /* * Create secondary database handles. @@ -232,11 +232,13 @@ csv_secondary_close() * Compare two keys. */ static int -compare_uint32(DB *db_arg, const DBT *a_arg, const DBT *b_arg) +compare_uint32(DB *db_arg, const DBT *a_arg, const DBT *b_arg, size_t *locp) { u_int32_t a, b; - db_arg = db_arg; /* Quiet compiler. */ + /* Quiet compiler. */ + db_arg = db_arg; + locp = NULL; memcpy(&a, a_arg->data, sizeof(u_int32_t)); memcpy(&b, b_arg->data, sizeof(u_int32_t)); diff --git a/examples/c/csv/load.c b/examples/c/csv/load.c index 74fadfe0..708fd0ea 100644 --- a/examples/c/csv/load.c +++ b/examples/c/csv/load.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/csv/load_main.c b/examples/c/csv/load_main.c index 1caeda00..5e42e406 100644 --- a/examples/c/csv/load_main.c +++ b/examples/c/csv/load_main.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -15,11 +15,12 @@ static int usage(void); /* * Globals */ -DB_ENV *dbenv; /* Database environment */ -DB *db; /* Primary database */ +DB_ENV *dbenv; /* Database environment */ +DB *db; /* Primary database */ DB **secondary; /* Secondaries */ -int verbose; /* Program verbosity */ -char *progname; /* Program name */ +int verbose; /* Program verbosity */ +char *progname; /* Program name */ +FILE *ffp; /* CSV file */ int main(int argc, char *argv[]) @@ -37,6 +38,7 @@ main(int argc, char *argv[]) else ++progname; verbose = 0; + ffp = NULL; /* Initialize arguments. */ home = NULL; @@ -46,8 +48,8 @@ main(int argc, char *argv[]) /* Process arguments. */ while ((ch = getopt(argc, argv, "F:f:h:V:v")) != EOF) switch (ch) { - case 'f': - if (freopen(optarg, "r", stdin) == NULL) { + case 'f': /* Required argument */ + if ((ffp = freopen(optarg, "r", stdin)) == NULL) { fprintf(stderr, "%s: %s\n", optarg, db_strerror(errno)); return (EXIT_FAILURE); @@ -76,7 +78,7 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - if (*argv != NULL) + if (*argv != NULL || ffp == NULL) return (usage()); /* diff --git a/examples/c/csv/query.c b/examples/c/csv/query.c index f41dc560..e2c4e223 100644 --- a/examples/c/csv/query.c +++ b/examples/c/csv/query.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/csv/query_main.c b/examples/c/csv/query_main.c index ed22283e..eb156367 100644 --- a/examples/c/csv/query_main.c +++ b/examples/c/csv/query_main.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/csv/util.c b/examples/c/csv/util.c index c8cfa6c0..bcc280cc 100644 --- a/examples/c/csv/util.c +++ b/examples/c/csv/util.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -156,11 +156,13 @@ secondary_callback(DB *db_arg, const DBT *key, const DBT *data, DBT *result) * Compare two keys. */ int -compare_double(DB *db_arg, const DBT *a_arg, const DBT *b_arg) +compare_double(DB *db_arg, const DBT *a_arg, const DBT *b_arg, size_t *locp) { double a, b; - db_arg = db_arg; /* Quiet compiler. */ + /* Quiet compiler. */ + db_arg = db_arg; + locp = NULL; memcpy(&a, a_arg->data, sizeof(double)); memcpy(&b, b_arg->data, sizeof(double)); @@ -172,11 +174,13 @@ compare_double(DB *db_arg, const DBT *a_arg, const DBT *b_arg) * Compare two keys. */ int -compare_ulong(DB *db_arg, const DBT *a_arg, const DBT *b_arg) +compare_ulong(DB *db_arg, const DBT *a_arg, const DBT *b_arg, size_t *locp) { u_long a, b; - db_arg = db_arg; /* Quiet compiler. */ + /* Quiet compiler. */ + db_arg = db_arg; + locp = NULL; memcpy(&a, a_arg->data, sizeof(u_long)); memcpy(&b, b_arg->data, sizeof(u_long)); diff --git a/examples/c/ex_access.c b/examples/c/ex_access.c index 67d248fe..8f3b5896 100644 --- a/examples/c/ex_access.c +++ b/examples/c/ex_access.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_apprec/ex_apprec.c b/examples/c/ex_apprec/ex_apprec.c index 0c19341f..81089355 100644 --- a/examples/c/ex_apprec/ex_apprec.c +++ b/examples/c/ex_apprec/ex_apprec.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_apprec/ex_apprec.h b/examples/c/ex_apprec/ex_apprec.h index b7e0da03..3ac65401 100644 --- a/examples/c/ex_apprec/ex_apprec.h +++ b/examples/c/ex_apprec/ex_apprec.h @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2002, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_apprec/ex_apprec.src b/examples/c/ex_apprec/ex_apprec.src index 91618c00..6c6893d4 100644 --- a/examples/c/ex_apprec/ex_apprec.src +++ b/examples/c/ex_apprec/ex_apprec.src @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2002, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_apprec/ex_apprec_rec.c b/examples/c/ex_apprec/ex_apprec_rec.c index 70eab4a5..7ed786f4 100644 --- a/examples/c/ex_apprec/ex_apprec_rec.c +++ b/examples/c/ex_apprec/ex_apprec_rec.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_blob.c b/examples/c/ex_blob.c new file mode 100644 index 00000000..1c074f7a --- /dev/null +++ b/examples/c/ex_blob.c @@ -0,0 +1,286 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved. + * + * $Id$ + */ + +#include <sys/types.h> + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define CMD_LEN 25 +#ifdef _WIN32 +extern int getopt(int, char * const *, const char *); +#else +#include <unistd.h> +#endif + +#include <db.h> + +int db_setup __P((const char *, FILE *, const char *)); +int db_teardown __P((const char *, FILE *, const char *)); +static int usage __P((void)); + +const char *progname = "ex_blob"; /* Program name. */ + +/* + * An example of a program that stores data items in Berkeley DB blob + * files. + */ +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + char *cmd; + const char *home; + + int ch; + home = "EX_BLOBDIR"; + while ((ch = getopt(argc, argv, "h:")) != EOF) + switch (ch) { + case 'h': + home = optarg; + break; + case '?': + default: + return (usage()); + } + argc -= optind; + argv += optind; + + if (argc != 0) + return (usage()); + + if ((cmd = malloc(strlen(home) + CMD_LEN)) == NULL) + return (EXIT_FAILURE); + +#ifdef _WIN32 + sprintf(cmd, "rmdir %s /q/s", home); +#else + sprintf(cmd, "rm -rf %s", home); +#endif + system(cmd); + sprintf(cmd, "mkdir %s", home); + system(cmd); + free(cmd); + + printf("Setup env\n"); + if (db_setup(home, stderr, progname) != 0) + return (EXIT_FAILURE); + + return (EXIT_SUCCESS); +} + +int +db_setup(home, errfp, progname) + const char *home, *progname; + FILE *errfp; +{ + DBC *dbc; + DB_ENV *dbenv; + DB *dbp; + DB_STREAM *dbs; + DB_TXN *txn; + DBT data, key; + int ret; + db_off_t size; + unsigned int i; + + dbc = NULL; + dbenv = NULL; + dbp = NULL; + dbs = NULL; + txn = NULL; + memset (&data, 0, sizeof(DBT)); + + /* + * Create an environment object and initialize it for error + * reporting. + */ + if ((ret = db_env_create(&dbenv, 0)) != 0) { + fprintf(errfp, "%s: %s\n", progname, db_strerror(ret)); + return (1); + } + dbenv->set_errfile(dbenv, errfp); + dbenv->set_errpfx(dbenv, progname); + + /* + * We want to specify the shared memory buffer pool cachesize. + */ + if ((ret = dbenv->set_cachesize(dbenv, 0, 64 * 1024 *1024, 0)) != 0) { + dbenv->err(dbenv, ret, "set_cachesize"); + goto err; + } + + /* Enable blob files and set the size threshold. */ + if ((ret = dbenv->set_blob_threshold(dbenv, 1000, 0)) != 0) { + dbenv->err(dbenv, ret, "set_blob_threshold"); + goto err; + } + + /* Open the environment with full transactional support. */ + if ((ret = dbenv->open(dbenv, home, + DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | + DB_INIT_TXN, 0644)) != 0) { + dbenv->err(dbenv, ret, "environment open: %s", home); + goto err; + } + + /* Open a database in the environment. */ + if ((ret = db_create(&dbp, dbenv, 0)) != 0) { + dbenv->err(dbenv, ret, "database create"); + goto err; + } + + /* Open a database with btree access method. */ + if ((ret = dbp->open(dbp, NULL, "exblob_db1.db", NULL, + DB_BTREE, DB_CREATE|DB_AUTO_COMMIT,0644)) != 0) { + dbenv->err(dbenv, ret, "database open"); + goto err; + } + + /* Insert an item that will overflow. */ + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + key.ulen = key.size = sizeof(int); + key.flags = DB_DBT_USERMEM; + + data.size = data.ulen = 4000; + data.data = malloc(data.size); + for (i = 0; i < data.size; i++) + ((char *)data.data)[i] = 'a' + (i % 26); + data.flags = DB_DBT_USERMEM; + +#define COUNT 5000 + for (i = 1; i < COUNT; i++) { + key.data = &i; + /* Use a mixture of blob and onpage items. */ + if (i%23 == 0) + data.size = 20; + if ((ret = dbp->put(dbp, NULL, &key, &data, 0)) != 0) { + dbenv->err(dbenv, ret, "blob put"); + goto err; + } + if (i%23 == 0) + data.size = data.ulen; + } + + for (i = 1; i < COUNT; i += 2) { + key.data = &i; + memset(data.data, 0, data.size); + if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) != 0) { + dbenv->err(dbenv, ret, "blob get"); + goto err; + } + if (strncmp((char *)data.data, "abcdefghijklmno", 15) != 0) + printf("blob data mismatch\n"); + } + + /* Blobs can also be accessed using the DB_STREAM API. */ + if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0){ + dbenv->err(dbenv, ret, "txn"); + goto err; + } + + if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0) { + dbenv->err(dbenv, ret, "cursor"); + goto err; + } + + /* + * Set the cursor to a blob. Use DB_DBT_PARTIAL with + * dlen == 0 to avoid getting any blob data. + */ + data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; + data.dlen = 0; + if ((ret = dbc->get(dbc, &key, &data, DB_FIRST)) != 0) { + dbenv->err(dbenv, ret, "Not a blob"); + goto err; + } + data.flags = DB_DBT_USERMEM; + + /* Create a stream on the blob the cursor points to. */ + if ((ret = dbc->db_stream(dbc, &dbs, DB_STREAM_WRITE)) != 0) { + dbenv->err(dbenv, 0, "Creating stream."); + goto err; + } + /* Get the size of the blob. */ + if ((ret = dbs->size(dbs, &size, 0)) != 0) { + dbenv->err(dbenv, 0, "Stream size."); + goto err; + } + /* Read from the blob. */ + if ((ret = dbs->read(dbs, &data, 0, (u_int32_t)size, 0)) != 0) { + dbenv->err(dbenv, 0, "Stream read."); + goto err; + } + /* Write data to the blob, increasing its size. */ + if ((ret = dbs->write(dbs, &data, size/2, 0)) != 0) { + dbenv->err(dbenv, 0, "Stream write."); + goto err; + } + /* Close the stream. */ + if ((ret = dbs->close(dbs, 0)) != 0) { + dbenv->err(dbenv, 0, "Stream close."); + goto err; + } + dbs = NULL; + dbc->close(dbc); + dbc = NULL; + txn->commit(txn, 0); + txn = NULL; + free(data.data); + data.data = NULL; + + for (i = 3; i < COUNT; i += 2) { + key.data = &i; + if ((ret = dbp->del(dbp, NULL, &key, 0)) != 0) { + dbenv->err(dbenv, ret, "blob del"); + goto err; + } + } + + /* Close the database handle. */ + if ((ret = dbp->close(dbp, 0)) != 0) { + fprintf(stderr, "database close: %s\n", db_strerror(ret)); + return (1); + } + + /* Close the environment handle. */ + if ((ret = dbenv->close(dbenv, 0)) != 0) { + fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret)); + return (1); + } + return (0); + +err: if (data.data != NULL) + free(data.data); + if (dbs != NULL) + dbs->close(dbs, 0); + if (txn != NULL) + txn->abort(txn); + if (dbc != NULL) + dbc->close(dbc); + if (dbp != NULL) + dbp->close(dbp, 0); + if (dbenv != NULL) + dbenv->close(dbenv, 0); + + return (ret); +} + +static int +usage() +{ + (void)fprintf(stderr, + "usage: %s [-h home] \n", progname); + return (EXIT_FAILURE); +} diff --git a/examples/c/ex_btrec.c b/examples/c/ex_btrec.c index 85a910d9..817229b6 100644 --- a/examples/c/ex_btrec.c +++ b/examples/c/ex_btrec.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id: ex_btrec.c,v 0f73af5ae3da 2010/05/10 05:38:40 alexander $ */ diff --git a/examples/c/ex_bulk.c b/examples/c/ex_bulk.c index bc3ec26e..5120fbec 100644 --- a/examples/c/ex_bulk.c +++ b/examples/c/ex_bulk.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -16,6 +16,7 @@ #include <assert.h> #include <stdlib.h> #include <string.h> +#include <time.h> #define DATABASE "ex_bulk.db" /* Database name */ #define DATALEN 20 /* The length of data */ @@ -54,8 +55,9 @@ int bulk_delete(DB_ENV *, DB *, int, int, int *, int *, int); int bulk_delete_sec(DB_ENV *, DB *, int, int, int *, int *, int); int bulk_fill(DB_ENV *, DB *, int, int, int *, int *, int); int bulk_get(DB_ENV *, DB *, int, int, int, int *, int); -int compare_int(DB *, const DBT *, const DBT *); -DB_ENV *db_init(char *, char *, u_int); +int compare_int(DB *, const DBT *, const DBT *, size_t *); +int db_init(DB_ENV *, DB **, DB**, int, int, int); +DB_ENV *env_init(char *, char *, u_int); int get_first_str(DB *, const DBT *, const DBT *, DBT *); int get_string(const char *, char *, int); int main(int, char *[]); @@ -82,25 +84,27 @@ main(argc, argv) struct timeval start_time, end_time; double secs; u_int cache, pagesize; - int biter, ch, count, dups, init, iter, num; - int ret, rflag, sflag, bulk, delete, pair, verbose; + int biter, ch, count, delete, dups, init, iter, num; + int pair, ret, rflag, sflag, verbose; dbp = sdbp = NULL; dbenv = NULL; txnp = NULL; iter = num = 1000000; - dups = init = rflag = sflag = bulk = delete = verbose = 0; + delete = dups = init = rflag = sflag = verbose = 0; pagesize = 65536; cache = 1000 * pagesize; - while ((ch = getopt(argc, argv, "c:d:i:n:p:vDIRSU")) != EOF) + while ((ch = getopt(argc, argv, "c:d:i:n:p:vDIRS")) != EOF) switch (ch) { case 'c': cache = (u_int)atoi(optarg); break; case 'd': dups = atoi(optarg); + if (dups < 0) + usage(); break; case 'i': iter = atoi(optarg); @@ -126,9 +130,6 @@ main(argc, argv) case 'S': sflag = 1; break; - case 'U': - bulk = 1; - break; case '?': default: usage(); @@ -142,78 +143,16 @@ main(argc, argv) system("mkdir EX_BULK"); } - if ((dbenv = db_init("EX_BULK", "ex_bulk", cache)) == NULL) + if ((dbenv = env_init("EX_BULK", "ex_bulk", cache)) == NULL) return (-1); if (init) exit(0); /* Create and initialize database object, open the database. */ - if ((ret = db_create(&dbp, dbenv, 0)) != 0) { - fprintf(stderr, - "%s: db_create: %s\n", progname, db_strerror(ret)); - exit(EXIT_FAILURE); - } - dbp->set_errfile(dbp, stderr); - dbp->set_errpfx(dbp, progname); - if ((ret = dbp->set_bt_compare(dbp, compare_int)) != 0) { - dbp->err(dbp, ret, "set_bt_compare"); - goto err; - } - if ((ret = dbp->set_pagesize(dbp, pagesize)) != 0) { - dbp->err(dbp, ret, "set_pagesize"); - goto err; - } - if (dups && (ret = dbp->set_flags(dbp, DB_DUP)) != 0) { - dbp->err(dbp, ret, "set_flags"); - goto err; - } - - if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0) - goto err; - - if ((ret = dbp->open(dbp, txnp, DATABASE, "primary", DB_BTREE, - DB_CREATE , 0664)) != 0) { - dbp->err(dbp, ret, "%s: open", DATABASE); - if (txnp != NULL) - (void)txnp->abort(txnp); - goto err; - } - - if (sflag) { - /* - * Open secondary database. The keys in secondary database - * are the first charactor in str of struct data in data - * field of primary database. - */ - if ((ret = db_create(&sdbp, dbenv, 0)) != 0) { - fprintf(stderr, "%s: db_create: %s\n", - progname, db_strerror(ret)); - exit(EXIT_FAILURE); - } - if ((ret = sdbp->set_flags(sdbp, DB_DUPSORT)) != 0) { - sdbp->err(sdbp, ret, "set_flags"); - goto err; - } - if ((ret = sdbp->open(sdbp, txnp, DATABASE, "secondary", - DB_BTREE, DB_CREATE, 0664)) != 0) { - sdbp->err(sdbp, ret, "%s: secondary open", DATABASE); - if (txnp != NULL) - (void)txnp->abort(txnp); - goto err; - } - if ((ret = dbp->associate(dbp, txnp, sdbp, get_first_str, - 0)) != 0) { - dbp->err(dbp, ret, "%s: associate", DATABASE); - if (txnp != NULL) - (void)txnp->abort(txnp); - goto err; - } - } - - if ((ret = txnp->commit(txnp, 0)) != 0) - goto err; - txnp = NULL; + if ((ret = db_init(dbenv, &dbp, &sdbp, dups, sflag, pagesize)) != 0) + return (-1); + srand((int)time(NULL)); if (rflag) { /* Time the get loop. */ (void)gettimeofday(&start_time, NULL); @@ -334,10 +273,9 @@ bulk_delete(dbenv, dbp, num, dups, countp, iterp, verbose) j = rand() % num; /* - * Need to account for proper buffer size, the buffer must be at - * least as large as the page size of the underlying database, - * aligned for unsigned integer access, and be a multiple of 1024 - * bytes in size. + * The buffer must be at least as large as the page size of the + * underlying database and aligned for unsigned integer access. + * Its size must be a multiple of 1024 bytes. */ key.ulen = (u_int32_t)UPDATES_PER_BULK_PUT * (sizeof(u_int32_t) + DATALEN) * 1024; @@ -348,22 +286,23 @@ bulk_delete(dbenv, dbp, num, dups, countp, iterp, verbose) memset(data_val, 0, DATALEN); /* - * If DB_MULTIPLE, delete all records with a specified set of keys - * in a DBT. The DBT is constructed by DB_MULTIPLE_WRITE_NEXT. If - * DB_MULTIPLE_KEY, delete a specific set of key/data pairs in the - * DBT constructed by DB_MULTIPLE_KEY_WRITE_NEXT. Here, delete - * keys before the random key, if there are duplicate records, - * delete duplicate pairs with DB_MULTIPLE_KEY, unless, delete keys - * with DB_MULTIPLE. + * Bulk delete all records of a specific set of keys which includes all + * non-negative integers smaller than the random key. The random key is + * a random non-negative integer smaller than "num". + * If DB_MULTIPLE, construct the key DBT by the DB_MULTIPLE_WRITE_NEXT + * with the specific set of keys. If DB_MULTIPLE_KEY, construct the key + * DBT by the DB_MULTIPLE_KEY_WRITE_NEXT with all key/data pairs of the + * specific set of keys. */ - flag |= (dups) ? DB_MULTIPLE : DB_MULTIPLE_KEY; + flag |= (dups) ? DB_MULTIPLE_KEY : DB_MULTIPLE; DB_MULTIPLE_WRITE_INIT(ptrk, &key); for (i = 0; i < j; i++) { if (i % UPDATES_PER_BULK_PUT == 0) { if (txnp != NULL) { - if ((ret = txnp->commit(txnp, 0)) != 0) - goto err; + ret = txnp->commit(txnp, 0); txnp = NULL; + if (ret != 0) + goto err; } if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0) @@ -371,24 +310,24 @@ bulk_delete(dbenv, dbp, num, dups, countp, iterp, verbose) } if (dups) { - DB_MULTIPLE_WRITE_NEXT(ptrk, &key, &i, sizeof(i)); - assert(ptrk != NULL); - count++; - if (verbose) - printf("Delete key: %d\n", i); - } else { data_val->id = 0; + get_string(tstring, data_val->str, i); do { - get_string(tstring, data_val->str, i); DB_MULTIPLE_KEY_WRITE_NEXT(ptrk, &key, &i, sizeof(i), data_val, DATALEN); assert(ptrk != NULL); count++; if (verbose) printf( -"Delete key: %d, \tdata: (id %d, str %s)\n", +"Delete key: %d, \tdata: (id %d, str %s)\n", i, data_val->id, data_val->str); - } while (++data_val->id < dups); + } while (data_val->id++ < dups); + } else { + DB_MULTIPLE_WRITE_NEXT(ptrk, &key, &i, sizeof(i)); + assert(ptrk != NULL); + count++; + if (verbose) + printf("Delete key: %d\n", i); } if ((i + 1) % UPDATES_PER_BULK_PUT == 0) { @@ -452,10 +391,9 @@ bulk_delete_sec(dbenv, dbp, num, pair, countp, iterp, verbose) rc = rand() % (STRLEN - 1); /* - * Need to account for proper buffer size, the buffer must be at - * least as large as the page size of the underlying database, - * aligned for unsigned integer access, and be a multiple of - * 1024 bytes in size. + * The buffer must be at least as large as the page size of the + * underlying database and aligned for unsigned integer access. + * Its size must be a multiple of 1024 bytes. */ key.ulen = (u_int32_t)UPDATES_PER_BULK_PUT * (sizeof(u_int32_t) + DATALEN) * 1024; @@ -464,19 +402,23 @@ bulk_delete_sec(dbenv, dbp, num, pair, countp, iterp, verbose) memset(key.data, 0, key.ulen); /* - * Bulk delete records from a random key, which is one of charaters - * in tstring. If DB_MULTIPLE, delete all characters before the random - * key in the tstring. If DB_MULTIPLE_KEY, get duplicate data to the - * specified keys and delete key/data pairs. + * Bulk delete all records of a specific set of keys which includes all + * characters before the random key in the tstring. The random key is + * one of the characters in the tstring. + * If DB_MULTIPLE, construct the key DBT by the DB_MULTIPLE_WRITE_NEXT + * with the specific set of keys. If DB_MULTIPLE_KEY, construct the key + * DBT by the DB_MULTIPLE_KEY_WRITE_NEXT with all key/data pairs of the + * specific set of keys. */ flag |= (pair) ? DB_MULTIPLE_KEY : DB_MULTIPLE; DB_MULTIPLE_WRITE_INIT(ptrk, &key); for (i = 0; i <= rc; i++) { if (i % UPDATES_PER_BULK_PUT == 0) { if (txnp != NULL) { - if ((ret = txnp->commit(txnp, 0)) != 0) - goto err; + ret = txnp->commit(txnp, 0); txnp = NULL; + if (ret != 0) + goto err; } if ((ret = dbenv->txn_begin( dbenv, NULL, &txnp, 0)) != 0) @@ -570,11 +512,10 @@ bulk_fill(dbenv, dbp, num, dups, countp, iterp, verbose) memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); - /* - * Need to account for proper buffer size, + /* * The buffer must be at least as large as the page size of - * the underlying database, aligned for unsigned integer - * access, and be a multiple of 1024 bytes in size. + * the underlying database and aligned for unsigned integer + * access. Its size must be a multiple of 1024 bytes. */ key.ulen = (u_int32_t) UPDATES_PER_BULK_PUT * (sizeof(u_int32_t) + DATALEN) * 1024; @@ -589,12 +530,11 @@ bulk_fill(dbenv, dbp, num, dups, countp, iterp, verbose) memset(data.data, 0, data.ulen); /* - * We could bulk insert with either DB_MULTIPLE in two buffers or - * DB_MULTIPLE_KEY in one buffer. With DB_MULTIPLE, all keys are - * constructed in key DBT, all data is constructed in data DBT. - * With DB_MULTIPLE_KEY, all key/data pairs are constructed in - * the key DBT. Here, we use DB_MULTIPLE mode when there are - * duplicate records. + * Bulk insert with either DB_MULTIPLE in two buffers or + * DB_MULTIPLE_KEY in a single buffer. With DB_MULTIPLE, all keys are + * constructed in the key DBT, and all data is constructed in the data + * DBT. With DB_MULTIPLE_KEY, all key/data pairs are constructed in the + * key Dbt. We use DB_MULTIPLE mode when there are duplicate records. */ flag |= (dups) ? DB_MULTIPLE : DB_MULTIPLE_KEY; DB_MULTIPLE_WRITE_INIT(ptrk, &key); @@ -603,17 +543,18 @@ bulk_fill(dbenv, dbp, num, dups, countp, iterp, verbose) for (i = 0; i < num; i++) { if (i % UPDATES_PER_BULK_PUT == 0) { if (txnp != NULL) { - if ((ret = txnp->commit(txnp, 0)) != 0) - goto err; + ret = txnp->commit(txnp, 0); txnp = NULL; + if (ret != 0) + goto err; } if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0) goto err; } data_val->id = 0; + get_string(tstring, data_val->str, i); do { - get_string(tstring, data_val->str, i); if (dups) { DB_MULTIPLE_WRITE_NEXT(ptrk, &key, &i, sizeof(i)); @@ -622,7 +563,7 @@ bulk_fill(dbenv, dbp, num, dups, countp, iterp, verbose) data_val, DATALEN); assert(ptrd != NULL); } else { - DB_MULTIPLE_KEY_WRITE_NEXT(ptrk, + DB_MULTIPLE_KEY_WRITE_NEXT(ptrk, &key, &i, sizeof(i), data_val, DATALEN); assert(ptrk != NULL); } @@ -631,7 +572,7 @@ bulk_fill(dbenv, dbp, num, dups, countp, iterp, verbose) "Insert key: %d, \t data: (id %d, str %s)\n", i, data_val->id, data_val->str); count++; - } while (++data_val->id < dups); + } while (data_val->id++ < dups); if ((i + 1) % UPDATES_PER_BULK_PUT == 0) { switch (ret = dbp->put(dbp, txnp, &key, &data, flag)) { case 0: @@ -698,7 +639,6 @@ bulk_get(dbenv, dbp, num, dups, iter, countp, verbose) /* Initialize key DBT and data DBT, malloc bulk buffer. */ memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); - key.data = &j; key.size = sizeof(j); data.flags = DB_DBT_USERMEM; data.data = malloc(DATALEN * 16 * 1024); @@ -715,13 +655,18 @@ bulk_get(dbenv, dbp, num, dups, iter, countp, verbose) goto err; /* - * Bulk retrieve from a random key. Use DB_MULTIPLE_INIT to - * initialize variables for bulk retrieval. If there are - * duplicate records, use DB_MULTIPLE_NEXT to iterate them - * in the buffer. Unless, use DB_MULTIPLE_KEY_NEXT to iterate - * records after the random key. + * Bulk retrieve by a random key which is a random + * non-negative integer smaller than "num". + * If there are duplicates in the database, retrieve + * with DB_MULTIPLE and use the DB_MULTIPLE_NEXT + * to iterate the data of the random key in the data + * DBT. Otherwise retrieve with DB_MULTIPLE_KEY and use + * the DB_MULTIPLE_KEY_NEXT to iterate the + * key/data pairs of the specific set of keys which + * includes all integers >= the random key and < "num". */ j = rand() % num; + key.data = &j; if ((ret = dbcp->get(dbcp, &key, &data, flags)) != 0) goto err; DB_MULTIPLE_INIT(pointer, &data); @@ -751,15 +696,23 @@ bulk_get(dbenv, dbp, num, dups, iter, countp, verbose) } } - if ((ret = dbcp->close(dbcp)) != 0) + ret = dbcp->close(dbcp); + dbcp = NULL; + if (ret != 0) goto err; - if ((ret = txnp->commit(txnp, 0)) != 0) + + ret = txnp->commit(txnp, 0); + txnp = NULL; + if (ret != 0) goto err; } *countp = count; -err: +err: if (dbcp != NULL) + (void)dbcp->close(dbcp); + if (txnp != NULL) + (void)txnp->abort(txnp); if (ret != 0) dbp->err(dbp, ret, "get"); free(data.data); @@ -767,13 +720,15 @@ err: } int -compare_int(dbp, a, b) +compare_int(dbp, a, b, locp) DB *dbp; const DBT *a, *b; + size_t *locp; { int ai, bi; dbp = NULL; + locp = NULL; /* * Returns: @@ -788,10 +743,102 @@ compare_int(dbp, a, b) /* * db_init -- + * Open the database. + */ +int +db_init(dbenv, dbpp, sdbpp, dups, sflag, pagesize) + DB_ENV *dbenv; + DB **dbpp, **sdbpp; + int dups, sflag, pagesize; +{ + DB *dbp, *sdbp; + DB_TXN *txnp; + int ret; + + dbp = sdbp = NULL; + txnp = NULL; + ret = 0; + + if ((ret = db_create(&dbp, dbenv, 0)) != 0) { + fprintf(stderr, + "%s: db_create: %s\n", progname, db_strerror(ret)); + return (ret); + } + dbp->set_errfile(dbp, stderr); + dbp->set_errpfx(dbp, progname); + if ((ret = dbp->set_bt_compare(dbp, compare_int)) != 0) { + dbp->err(dbp, ret, "set_bt_compare"); + goto err; + } + if ((ret = dbp->set_pagesize(dbp, pagesize)) != 0) { + dbp->err(dbp, ret, "set_pagesize"); + goto err; + } + if (dups && (ret = dbp->set_flags(dbp, DB_DUP)) != 0) { + dbp->err(dbp, ret, "set_flags"); + goto err; + } + + if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0) + goto err; + + if ((ret = dbp->open(dbp, txnp, DATABASE, "primary", DB_BTREE, + DB_CREATE , 0664)) != 0) { + dbp->err(dbp, ret, "%s: open", DATABASE); + goto err; + } + *dbpp = dbp; + + if (sflag) { + /* + * Open secondary database. The keys in secondary database + * are the first charactor in str of struct data in data + * field of primary database. + */ + if ((ret = db_create(&sdbp, dbenv, 0)) != 0) { + fprintf(stderr, "%s: db_create: %s\n", + progname, db_strerror(ret)); + goto err; + } + if ((ret = sdbp->set_flags(sdbp, DB_DUPSORT)) != 0) { + sdbp->err(sdbp, ret, "set_flags"); + goto err; + } + if ((ret = sdbp->open(sdbp, txnp, DATABASE, "secondary", + DB_BTREE, DB_CREATE, 0664)) != 0) { + sdbp->err(sdbp, ret, "%s: secondary open", DATABASE); + goto err; + } + if ((ret = dbp->associate(dbp, txnp, sdbp, get_first_str, + 0)) != 0) { + dbp->err(dbp, ret, "%s: associate", DATABASE); + goto err; + } + } + *sdbpp = sdbp; + + ret = txnp->commit(txnp, 0); + txnp = NULL; + if (ret != 0) + goto err; + + return (0); + +err: if (txnp != NULL) + (void)txnp->abort(0); + if (sdbp != NULL) + (void)sdbp->close(sdbp, 0); + if (dbp != NULL) + (void)dbp->close(dbp, 0); + return (ret); +} + +/* + * env_init -- * Initialize the environment. */ DB_ENV * -db_init(home, prefix, cachesize) +env_init(home, prefix, cachesize) char *home, *prefix; u_int cachesize; { @@ -804,8 +851,10 @@ db_init(home, prefix, cachesize) } dbenv->set_errfile(dbenv, stderr); dbenv->set_errpfx(dbenv, prefix); - (void)dbenv->set_cachesize(dbenv, 0, - cachesize == 0 ? 50 * 1024 * 1024 : (u_int32_t)cachesize, 0); + if ((ret = dbenv->set_cachesize(dbenv, 0, cachesize, 0)) != 0) { + dbenv->err(dbenv, ret, "DB_ENV->set_cachesize"); + return (NULL); + } if ((ret = dbenv->open(dbenv, home, DB_CREATE | DB_INIT_MPOOL | DB_INIT_TXN | DB_INIT_LOCK, 0)) != 0) { @@ -857,11 +906,10 @@ usage() -n number of keys [1000000] \n\ -p pagesize [65536] \n\ -v verbose output \n\ - -D perform bulk delete \n\ + -D perform bulk delete \n\ -I just initialize the environment \n\ -R perform bulk read \n\ - -S perform bulk read in secondary database \n\ - -U perform bulk update \n", + -S perform bulk operation in secondary database \n", progname); exit(EXIT_FAILURE); } diff --git a/examples/c/ex_env.c b/examples/c/ex_env.c index dfc436d6..80c66e89 100644 --- a/examples/c/ex_env.c +++ b/examples/c/ex_env.c @@ -1,13 +1,14 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ #include <sys/types.h> +#include <errno.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> @@ -25,6 +26,8 @@ int db_teardown __P((const char *, const char *, FILE *, const char *)); static int usage __P((void)); const char *progname = "ex_env"; /* Program name. */ +int EnvFlags = + DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN; /* * An example of a program creating/configuring a Berkeley DB environment. @@ -37,15 +40,15 @@ main(argc, argv) extern char *optarg; extern int optind; const char *data_dir, *home; - int ch; + /* * All of the shared database files live in home, but * data files will live in data_dir. */ home = "TESTDIR"; data_dir = "data"; - while ((ch = getopt(argc, argv, "h:d:")) != EOF) + while ((ch = getopt(argc, argv, "h:d:l")) != EOF) switch (ch) { case 'h': home = optarg; @@ -53,6 +56,9 @@ main(argc, argv) case 'd': data_dir = optarg; break; + case 'l': + EnvFlags |= DB_LOCKDOWN; + break; case '?': default: return (usage()); @@ -108,10 +114,12 @@ db_setup(home, data_dir, errfp, progname) (void)dbenv->set_data_dir(dbenv, data_dir); /* Open the environment with full transactional support. */ - if ((ret = dbenv->open(dbenv, home, - DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | - DB_INIT_TXN, 0644)) != 0) { + if ((ret = dbenv->open(dbenv, home, EnvFlags, 0644)) != 0) { dbenv->err(dbenv, ret, "environment open: %s", home); + if (ret == ENOENT) { + printf("Please check whether home dir \"%s\" existed.\n", + home); + } dbenv->close(dbenv, 0); return (1); } @@ -129,8 +137,12 @@ db_setup(home, data_dir, errfp, progname) /* Open a database with DB_BTREE access method. */ if ((ret = dbp->open(dbp, NULL, "exenv_db1.db", NULL, - DB_BTREE, DB_CREATE,0644)) != 0) { + DB_BTREE, DB_CREATE, 0644)) != 0) { fprintf(stderr, "database open: %s\n", db_strerror(ret)); + if (ret == ENOENT) { + printf("Please check whether data dir \"%s\" " + "exists under \"%s\".\n", data_dir, home); + } return (1); } @@ -178,6 +190,6 @@ static int usage() { (void)fprintf(stderr, - "usage: %s [-h home] [-d data_dir]\n", progname); + "usage: %s [-l] [-h home] [-d data_dir]\n", progname); return (EXIT_FAILURE); } diff --git a/examples/c/ex_heap.c b/examples/c/ex_heap.c index 990c9365..474be909 100644 --- a/examples/c/ex_heap.c +++ b/examples/c/ex_heap.c @@ -1,7 +1,7 @@ /* * See the file LICENSE for redistribution information. * - * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ * @@ -24,7 +24,7 @@ #ifndef lint static const char copyright[] = - "Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved.\n"; + "Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved.\n"; #endif #define BUFFER_LEN 30 /* Buffer size to hold data */ @@ -66,7 +66,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) #include <unistd.h> #endif -int compare_int(DB *, const DBT *, const DBT *); +int compare_int(DB *, const DBT *, const DBT *, size_t *); int delete_recs __P((DB *, DB_ENV *, int)); int file_size __P((DB *, DBTYPE, int *)); int generate_data __P((char [], int, int)); @@ -622,13 +622,15 @@ err: } int -compare_int(dbp, a, b) +compare_int(dbp, a, b, locp) DB *dbp; const DBT *a, *b; + size_t *locp; { int ai, bi; dbp = NULL; + locp = NULL; /* * Returns: diff --git a/examples/c/ex_lock.c b/examples/c/ex_lock.c index 32e22b0e..259d5057 100644 --- a/examples/c/ex_lock.c +++ b/examples/c/ex_lock.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_mpool.c b/examples/c/ex_mpool.c index c7a24283..c13e8962 100644 --- a/examples/c/ex_mpool.c +++ b/examples/c/ex_mpool.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_rep/base/rep_base.c b/examples/c/ex_rep/base/rep_base.c index c9443e4d..56662220 100644 --- a/examples/c/ex_rep/base/rep_base.c +++ b/examples/c/ex_rep/base/rep_base.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -169,6 +169,8 @@ main(argc, argv) goto err; } + machtab_destroy(machtab); + /* Finish checkpoint and log archive threads. */ if ((ret = finish_support_threads(&ckp_thr, &lga_thr)) != 0) goto err; diff --git a/examples/c/ex_rep/base/rep_base.h b/examples/c/ex_rep/base/rep_base.h index 27901349..48d5d3ac 100644 --- a/examples/c/ex_rep/base/rep_base.h +++ b/examples/c/ex_rep/base/rep_base.h @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -71,6 +71,8 @@ typedef SOCKET socket_t; #define readsocket(s, buf, sz) recv((s), (buf), (int)(sz), 0) #define writesocket(s, buf, sz) send((s), (const char *)(buf), (int)(sz), 0) #define net_errno WSAGetLastError() +#undef SHUT_RDWR +#define SHUT_RDWR SD_BOTH #else /* !_WIN32 */ @@ -104,9 +106,10 @@ socket_t get_accepted_socket __P((const char *, int)); socket_t get_connected_socket __P((machtab_t *, const char *, const char *, int, int *, int *)); int get_next_message __P((socket_t, DBT *, DBT *)); -socket_t listen_socket_init __P((const char *, int)); +socket_t listen_socket_init __P((const char *, int, machtab_t *)); socket_t listen_socket_accept __P((machtab_t *, const char *, socket_t, int *)); +int machtab_destroy __P((machtab_t *)); int machtab_getinfo __P((machtab_t *, int, u_int32_t *, int *)); int machtab_init __P((machtab_t **, int)); void machtab_parm __P((machtab_t *, int *, u_int32_t *)); diff --git a/examples/c/ex_rep/base/rep_msg.c b/examples/c/ex_rep/base/rep_msg.c index 8ed45f7f..bbcaed45 100644 --- a/examples/c/ex_rep/base/rep_msg.c +++ b/examples/c/ex_rep/base/rep_msg.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -80,6 +80,10 @@ hm_loop(args) for (ret = 0; ret == 0;) { if ((ret = get_next_message(fd, &rec, &control)) != 0) { + if (app->shared_data.app_finished) { + ret = 0; + goto netclose; + } /* * Close this connection; if it's the master call * for an election. @@ -183,6 +187,7 @@ hm_loop(args) "thread join failure"); goto out; } + free(ea); ea = NULL; } if ((ea = calloc(sizeof(elect_args), 1)) == NULL) { @@ -219,15 +224,21 @@ hm_loop(args) out: if ((t_ret = machtab_rem(tab, eid, 1)) != 0 && ret == 0) ret = t_ret; - +netclose: /* Don't close the environment before any children exit. */ - if (ea != NULL && thread_join(elect_thr, &status) != 0) - dbenv->errx(dbenv, "can't join election thread"); + if (ea != NULL) { + if (thread_join(elect_thr, &status) != 0) + dbenv->errx(dbenv, "can't join election thread"); + free(ea); + ea = NULL; + } - if (site_thrs != NULL) + if (site_thrs != NULL) { while (--nsites >= 0) if (thread_join(site_thrs[nsites], &status) != 0) dbenv->errx(dbenv, "can't join site thread"); + free(site_thrs); + } return ((void *)(uintptr_t)ret); } @@ -242,6 +253,7 @@ connect_thread(args) void *args; { DB_ENV *dbenv; + APP_DATA *app; const char *home, *progname; hm_loop_args *ha; connect_args *cargs; @@ -252,18 +264,20 @@ connect_thread(args) socket_t fd, ns; ha = NULL; + i = 0; cargs = (connect_args *)args; dbenv = cargs->dbenv; home = cargs->home; progname = cargs->progname; machtab = cargs->machtab; port = cargs->port; + app = dbenv->app_private; /* * Loop forever, accepting connections from new machines, * and forking off a thread to handle each. */ - if ((fd = listen_socket_init(progname, port)) < 0) { + if ((fd = listen_socket_init(progname, port, machtab)) < 0) { ret = errno; goto err; } @@ -271,7 +285,10 @@ connect_thread(args) for (i = 0; i < MAX_THREADS; i++) { if ((ns = listen_socket_accept(machtab, progname, fd, &eid)) == SOCKET_CREATION_FAILURE) { - ret = errno; + if (app->shared_data.app_finished) + ret = 0; + else + ret = errno; goto err; } if ((ha = calloc(sizeof(hm_loop_args), 1)) == NULL) { @@ -285,7 +302,7 @@ connect_thread(args) ha->eid = eid; ha->tab = machtab; ha->dbenv = dbenv; - if ((ret = thread_create(&hm_thrs[i++], NULL, + if ((ret = thread_create(&hm_thrs[i], NULL, hm_loop, (void *)ha)) != 0) { dbenv->errx(dbenv, "can't create thread for site"); goto err; @@ -297,12 +314,13 @@ connect_thread(args) dbenv->errx(dbenv, "Too many threads"); ret = ENOMEM; +err: /* Do not return until all threads have exited. */ while (--i >= 0) if (thread_join(hm_thrs[i], &status) != 0) dbenv->errx(dbenv, "can't join site thread"); -err: return (ret == 0 ? (void *)EXIT_SUCCESS : (void *)EXIT_FAILURE); + return (ret == 0 ? (void *)EXIT_SUCCESS : (void *)EXIT_FAILURE); } /* @@ -314,15 +332,15 @@ connect_all(args) void *args; { DB_ENV *dbenv; + APP_DATA *app; all_args *aa; const char *home, *progname; - hm_loop_args *ha; int failed, i, nsites, open, ret, *success; machtab_t *machtab; - thread_t *hm_thr; + thread_t empty_id, *hm_thr; repsite_t *sites; + void *status; - ha = NULL; aa = (all_args *)args; dbenv = aa->dbenv; progname = aa->progname; @@ -330,6 +348,9 @@ connect_all(args) machtab = aa->machtab; nsites = aa->nsites; sites = aa->sites; + status = NULL; + app = dbenv->app_private; + memset(&empty_id, 0, sizeof(thread_t)); ret = 0; hm_thr = NULL; @@ -353,6 +374,9 @@ connect_all(args) if (success[i]) continue; + if (app->shared_data.app_finished) + goto err; + ret = connect_site(dbenv, machtab, progname, &sites[i], &open, &hm_thr[i]); @@ -378,7 +402,15 @@ connect_all(args) sleep(1); } -err: if (success != NULL) +err: + for (i = 0; i < nsites; i++) { + if (!success[i] || + memcmp(&hm_thr[i], &empty_id, sizeof(thread_t)) == 0) + continue; + if (thread_join(hm_thr[i], &status) != 0) + dbenv->errx(dbenv, "can't join site thread"); + } + if (success != NULL) free(success); if (hm_thr != NULL) free(hm_thr); @@ -453,12 +485,16 @@ elect_thread(args) machtab_parm(machtab, &n, &timeout); (void)dbenv->rep_set_timeout(dbenv, DB_REP_ELECTION_TIMEOUT, timeout); - while ((ret = dbenv->rep_elect(dbenv, n, (n/2+1), 0)) != 0) + while ((ret = dbenv->rep_elect(dbenv, n, (n/2+1), 0)) != 0) { + if (app->shared_data.app_finished) + return (NULL); sleep(2); + } if (app->elected) { app->elected = 0; - if ((ret = dbenv->rep_start(dbenv, NULL, DB_REP_MASTER)) != 0) + if ((ret = dbenv->rep_start(dbenv, NULL, + DB_REP_MASTER)) != 0 && !app->shared_data.app_finished) dbenv->err(dbenv, ret, "can't start as master in election thread"); } diff --git a/examples/c/ex_rep/base/rep_net.c b/examples/c/ex_rep/base/rep_net.c index 29012536..e57e3af8 100644 --- a/examples/c/ex_rep/base/rep_net.c +++ b/examples/c/ex_rep/base/rep_net.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -70,6 +70,7 @@ struct __machtab { int current; int max; int nsites; + socket_t listenfd; }; /* Data structure that describes each entry in the machtab. */ @@ -113,6 +114,7 @@ machtab_init(machtabp, nsites) machtab->timeout_time = 2 * 1000000; /* 2 seconds. */ machtab->current = machtab->max = 0; machtab->nsites = nsites; + machtab->listenfd = SOCKET_CREATION_FAILURE; ret = mutex_init(&machtab->mtmutex, NULL); *machtabp = machtab; @@ -265,6 +267,47 @@ machtab_rem(machtab, eid, lock) return (ret); } +/* + * machtab_destroy -- + * Close the listening socket and all connecting sockets, + * So that all threads blocked on 'accept' and 'read' will be + * unblocked. + */ +int machtab_destroy(machtab) + machtab_t *machtab; +{ + int ret; + socket_t listenfd; + member_t *member; + + if ((ret = mutex_lock(&machtab->mtmutex)) != 0) { + fprintf(stderr, "can't lock mutex\n"); + return (ret); + } + + listenfd = machtab->listenfd; + machtab->listenfd = SOCKET_CREATION_FAILURE; + for (member = LIST_FIRST(&machtab->machlist); + member != NULL; + member = LIST_FIRST(&machtab->machlist)) { + LIST_REMOVE(member, links); + shutdown(member->fd, SHUT_RDWR); + (void)closesocket(member->fd); + free(member); + machtab->current--; + } + shutdown(listenfd, SHUT_RDWR); + (void)closesocket(listenfd); + machtab->nextid = 2; + machtab->current = machtab->max = 0; + + if ((ret = mutex_unlock(&machtab->mtmutex)) != 0) { + fprintf(stderr, "can't unlock mutex\n"); + return (ret); + } + return (ret); +} + void machtab_parm(machtab, nump, timeoutp) machtab_t *machtab; @@ -310,9 +353,10 @@ machtab_print(machtab) * in a thread that we're happy to let block. */ socket_t -listen_socket_init(progname, port) +listen_socket_init(progname, port, machtab) const char *progname; int port; + machtab_t *machtab; { socket_t s; int sockopt; @@ -349,6 +393,7 @@ listen_socket_init(progname, port) goto err; } + machtab->listenfd = s; return (s); err: closesocket(s); @@ -380,7 +425,8 @@ accept_wait: si_len = sizeof(si); ns = accept(s, (struct sockaddr *)&si, &si_len); if (ns == SOCKET_CREATION_FAILURE) { - fprintf(stderr, "can't accept incoming connection\n"); + if (machtab->listenfd != SOCKET_CREATION_FAILURE) + fprintf(stderr, "can't accept incoming connection\n"); return ns; } host = ntohl(si.sin_addr.s_addr); diff --git a/examples/c/ex_rep/common/rep_common.c b/examples/c/ex_rep/common/rep_common.c index a091adda..d7d2585a 100644 --- a/examples/c/ex_rep/common/rep_common.c +++ b/examples/c/ex_rep/common/rep_common.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -19,6 +19,18 @@ #define DATABASE "quote.db" #define SLEEPTIME 3 +/* + * Definition of thread-specific data key for PERM_FAILED structure + * stored in thread local storage. + */ +#ifdef _WIN32 +/* Windows style. */ +DWORD permfail_key; +#else +/* Posix style. */ +pthread_key_t permfail_key; +#endif + static int print_stocks __P((DB *)); /* @@ -346,15 +358,27 @@ doloop(dbenv, shared_data) { DB *dbp; DBT key, data; + permfail_t *pfinfo; char buf[BUFSIZE], *first, *price; u_int32_t flags; int ret; dbp = NULL; + pfinfo = NULL; ret = 0; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); + /* Allocate put/commit thread's PERM_FAILED structure. */ + if (shared_data->is_repmgr) { + if ((pfinfo = malloc(sizeof(permfail_t))) == NULL) + goto err; + if ((ret = thread_setspecific(permfail_key, pfinfo)) != 0) + goto err; + pfinfo->thread_name = "PutCommit"; + pfinfo->flag = 0; + } + for (;;) { printf("QUOTESERVER%s> ", shared_data->is_master ? "" : " (read-only)"); @@ -431,6 +455,16 @@ doloop(dbenv, shared_data) dbenv->err(dbenv, ret, "DB->open"); goto err; } + /* Check this thread's PERM_FAILED indicator. */ + if (shared_data->is_repmgr) { + pfinfo = (permfail_t *)thread_getspecific( + permfail_key); + if (pfinfo->flag) + printf( + "%s Thread: dbopen not durable.\n", + pfinfo->thread_name); + pfinfo->flag = 0; + } } if (first == NULL) { @@ -470,11 +504,23 @@ doloop(dbenv, shared_data) dbp->err(dbp, ret, "DB->put"); goto err; } + /* Check this thread's PERM_FAILED indicator. */ + if (shared_data->is_repmgr) { + pfinfo = (permfail_t *)thread_getspecific( + permfail_key); + if (pfinfo->flag) + printf( + "%s Thread: put %s %s not durable.\n", + pfinfo->thread_name, first, price); + pfinfo->flag = 0; + } } } err: if (dbp != NULL) (void)dbp->close(dbp, DB_NOSYNC); + if (pfinfo != NULL) + free(pfinfo); return (ret); } @@ -575,12 +621,24 @@ checkpoint_thread(args) { DB_ENV *dbenv; SHARED_DATA *shared; + permfail_t *pfinfo; supthr_args *ca; int i, ret; ca = (supthr_args *)args; dbenv = ca->dbenv; shared = ca->shared; + pfinfo = NULL; + + /* Allocate checkpoint thread's PERM_FAILED structure. */ + if (shared->is_repmgr) { + if ((pfinfo = malloc(sizeof(permfail_t))) == NULL) + return ((void *)EXIT_FAILURE); + if ((ret = thread_setspecific(permfail_key, pfinfo)) != 0) + return ((void *)EXIT_FAILURE); + pfinfo->thread_name = "Checkpoint"; + pfinfo->flag = 0; + } for (;;) { /* @@ -590,16 +648,30 @@ checkpoint_thread(args) */ for (i = 0; i < 60; i++) { sleep(1); - if (shared->app_finished == 1) + if (shared->app_finished == 1) { + if (pfinfo != NULL) + free(pfinfo); return ((void *)EXIT_SUCCESS); + } } /* Perform a checkpoint. */ if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0)) != 0) { dbenv->err(dbenv, ret, "Could not perform checkpoint.\n"); + if (pfinfo != NULL) + free(pfinfo); return ((void *)EXIT_FAILURE); } + /* Check this thread's PERM_FAILED indicator. */ + if (shared->is_repmgr) { + pfinfo = (permfail_t *)thread_getspecific( + permfail_key); + if (pfinfo->flag) + printf("%s Thread: checkpoint not durable.\n", + pfinfo->thread_name); + pfinfo->flag = 0; + } } } diff --git a/examples/c/ex_rep/common/rep_common.h b/examples/c/ex_rep/common/rep_common.h index edf3b67d..8f7d1348 100644 --- a/examples/c/ex_rep/common/rep_common.h +++ b/examples/c/ex_rep/common/rep_common.h @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -33,6 +33,7 @@ typedef struct { int is_master; int app_finished; int in_client_sync; + int is_repmgr; } SHARED_DATA; /* Arguments for support threads. */ @@ -41,6 +42,15 @@ typedef struct { SHARED_DATA *shared; } supthr_args; +/* + * Per-thread Replication Manager structure to associate a PERM_FAILED event + * with its originating transaction. + */ +typedef struct { + char *thread_name; + int flag; +} permfail_t; + /* Portability macros for basic threading & timing */ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -59,6 +69,16 @@ typedef HANDLE thread_t; ((WaitForSingleObject((thr), INFINITE) == WAIT_OBJECT_0) && \ GetExitCodeThread((thr), (LPDWORD)(statusp)) ? 0 : -1) +/* Thread-specific data key for PERM_FAILED structure for Windows. */ +extern DWORD permfail_key; +/* Thread local storage routine definitions for Windows. */ +#define thread_key_create(keyp) ((*keyp = TlsAlloc()) == \ + TLS_OUT_OF_INDEXES ? (int)GetLastError() : 0) +#define thread_key_delete(key) (TlsFree(key) ? 0 : (int)GetLastError()) +#define thread_setspecific(key, value) (TlsSetValue(key, value) ? 0 : \ + (int)GetLastError()) +#define thread_getspecific(key) TlsGetValue(key) + #else /* !_WIN32 */ #include <sys/time.h> #include <pthread.h> @@ -68,6 +88,14 @@ typedef pthread_t thread_t; pthread_create((thrp), (attr), (func), (arg)) #define thread_join(thr, statusp) pthread_join((thr), (statusp)) +/* Thread-specific data key for PERM_FAILED structure for Posix. */ +extern pthread_key_t permfail_key; +/* Thread local storage routine definitions for Posix. */ +#define thread_key_create(keyp) pthread_key_create(keyp, NULL) +#define thread_key_delete(key) pthread_key_delete(key) +#define thread_setspecific(key, value) pthread_setspecific(key, value) +#define thread_getspecific(key) pthread_getspecific(key) + #endif void *checkpoint_thread __P((void *)); diff --git a/examples/c/ex_rep/mgr/rep_mgr.c b/examples/c/ex_rep/mgr/rep_mgr.c index 0eaf1971..5c6d15f5 100644 --- a/examples/c/ex_rep/mgr/rep_mgr.c +++ b/examples/c/ex_rep/mgr/rep_mgr.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -115,6 +115,10 @@ main(argc, argv) dbenv->err(dbenv, ret, "Could not set heartbeat monitor timeout.\n"); + /* Create thread-specific data key for PERM_FAILED structure. */ + if ((ret = thread_key_create(&permfail_key)) != 0) + goto err; + /* * The following repmgr features may also be useful to your * application. See Berkeley DB documentation for more details. @@ -133,6 +137,7 @@ main(argc, argv) /* Start checkpoint and log archive threads. */ sup_args.dbenv = dbenv; sup_args.shared = &my_app_data.shared_data; + my_app_data.shared_data.is_repmgr = 1; if ((ret = start_support_threads(dbenv, &sup_args, &ckp_thr, &lga_thr)) != 0) goto err; @@ -163,6 +168,10 @@ main(argc, argv) goto err; } + /* Delete thread-specific data key for PERM_FAILED structure. */ + if ((ret = thread_key_delete(permfail_key)) != 0) + goto err; + err: if (dbenv != NULL && (t_ret = dbenv->close(dbenv, 0)) != 0) { @@ -183,8 +192,10 @@ event_callback(dbenv, which, info) { APP_DATA *app = dbenv->app_private; SHARED_DATA *shared = &app->shared_data; + permfail_t *pfinfo; int err; + pfinfo = NULL; switch (which) { case DB_EVENT_PANIC: @@ -213,8 +224,12 @@ event_callback(dbenv, which, info) * transaction will be flushed to the master site's * local disk storage for durability. */ + /* Set this thread's PERM_FAILED indicator. */ + pfinfo = (permfail_t *)thread_getspecific(permfail_key); + printf("%s Thread: ", pfinfo->thread_name); + pfinfo->flag = 1; printf( - "Insufficient acknowledgements to guarantee transaction durability.\n"); + "Insufficient acknowledgements for transaction durability.\n"); break; case DB_EVENT_REP_STARTUPDONE: diff --git a/examples/c/ex_rep_chan/rep_chan.c b/examples/c/ex_rep_chan/rep_chan.c index f5638264..1c661746 100644 --- a/examples/c/ex_rep_chan/rep_chan.c +++ b/examples/c/ex_rep_chan/rep_chan.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_rep_chan/rep_chan.h b/examples/c/ex_rep_chan/rep_chan.h index 9eff740d..7f46b5ff 100644 --- a/examples/c/ex_rep_chan/rep_chan.h +++ b/examples/c/ex_rep_chan/rep_chan.h @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved. * $Id$ */ diff --git a/examples/c/ex_rep_chan/rep_chan_util.c b/examples/c/ex_rep_chan/rep_chan_util.c index 07758152..b915e58d 100644 --- a/examples/c/ex_rep_chan/rep_chan_util.c +++ b/examples/c/ex_rep_chan/rep_chan_util.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -622,7 +622,7 @@ open_dbp(dbenv, is_master, dbpp) { DB *dbp; u_int32_t flags; - int ret; + int ret, t_ret; if ((ret = db_create(dbpp, dbenv, 0)) != 0) return (ret); @@ -647,13 +647,13 @@ open_dbp(dbenv, is_master, dbpp) if ((ret = dbp->open(dbp, NULL, DATABASE, NULL, DB_BTREE, flags, 0)) != 0) { if (ret == ENOENT) { - printf( "No stock database yet available.\n"); - if ((ret = dbp->close(dbp, 0)) != 0) { - dbenv->err(dbenv, ret, - "DB->close"); + printf("No stock database yet available.\n"); + *dbpp = NULL; + if ((t_ret = dbp->close(dbp, 0)) != 0) { + ret = t_ret; + dbenv->err(dbenv, ret, "DB->close"); goto err; } - *dbpp = NULL; } if (ret == DB_REP_HANDLE_DEAD || ret == DB_LOCK_DEADLOCK) { diff --git a/examples/c/ex_rep_gsg/rep_mgr_gsg.c b/examples/c/ex_rep_gsg/rep_mgr_gsg.c index aea8a05f..879a1c9d 100644 --- a/examples/c/ex_rep_gsg/rep_mgr_gsg.c +++ b/examples/c/ex_rep_gsg/rep_mgr_gsg.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_rep_gsg/simple_txn.c b/examples/c/ex_rep_gsg/simple_txn.c index c8feb16d..54406f4a 100644 --- a/examples/c/ex_rep_gsg/simple_txn.c +++ b/examples/c/ex_rep_gsg/simple_txn.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_sequence.c b/examples/c/ex_sequence.c index 28f0e199..dd01ec33 100644 --- a/examples/c/ex_sequence.c +++ b/examples/c/ex_sequence.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_stream.c b/examples/c/ex_stream.c index 209d6279..5bc0f0ed 100644 --- a/examples/c/ex_stream.c +++ b/examples/c/ex_stream.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_thread.c b/examples/c/ex_thread.c index 7b39c8eb..00e0c368 100644 --- a/examples/c/ex_thread.c +++ b/examples/c/ex_thread.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/ex_tpcb.c b/examples/c/ex_tpcb.c index 16807d2c..89a9210c 100644 --- a/examples/c/ex_tpcb.c +++ b/examples/c/ex_tpcb.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/getting_started/example_database_load.c b/examples/c/getting_started/example_database_load.c index 52127421..e09a1096 100644 --- a/examples/c/getting_started/example_database_load.c +++ b/examples/c/getting_started/example_database_load.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2004, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015 Oracle and/or its affiliates. All rights reserved. */ #include "gettingstarted_common.h" @@ -77,7 +77,7 @@ main(int argc, char *argv[]) /* Open all databases */ ret = databases_setup(&my_stock, "example_database_load", stderr); if (ret) { - fprintf(stderr, "Error opening databases\n"); + fprintf(stderr, "Error opening databases.\n"); databases_close(&my_stock); return (ret); } @@ -121,6 +121,7 @@ load_vendors_database(STOCK_DBS my_stock, char *vendor_file) return (-1); } + /* Iterate over the vendor file */ while (fgets(buf, MAXLINE, ifp) != NULL) { /* zero out the structure */ memset(&my_vendor, 0, sizeof(VENDOR)); @@ -164,6 +165,7 @@ load_vendors_database(STOCK_DBS my_stock, char *vendor_file) my_stock.vendor_dbp->put(my_stock.vendor_dbp, 0, &key, &data, 0); } /* end vendors database while loop */ + /* Close the vendor.txt file */ fclose(ifp); return (0); } @@ -220,6 +222,10 @@ load_inventory_database(STOCK_DBS my_stock, char *inventory_file) return (-1); } + /* + * Read the inventory.txt file line by line, saving each line off to + * the database as we go. + */ while (fgets(buf, MAXLINE, ifp) != NULL) { /* * Scan the line into the appropriate buffers and variables. @@ -238,10 +244,22 @@ load_inventory_database(STOCK_DBS my_stock, char *inventory_file) bufLen = 0; dataLen = 0; + /* + * We first store the fixed-length elements. This makes our code + * to retrieve this data from the database a little bit easier. + */ + + /* First discover how long the data element is. */ dataLen = sizeof(float); + /* Then copy it to our buffer */ memcpy(databuf, &price, dataLen); + /* + * Then figure out how much data is actually in our buffer. + * We repeat this pattern for all the data we want to store. + */ bufLen += dataLen; + /* Rinse, lather, repeat. */ dataLen = sizeof(int); memcpy(databuf + bufLen, &quantity, dataLen); bufLen += dataLen; @@ -251,11 +269,19 @@ load_inventory_database(STOCK_DBS my_stock, char *inventory_file) bufLen = pack_string(databuf, category, bufLen); bufLen = pack_string(databuf, vendor, bufLen); + /* + * Now actually save the contents of the buffer off + * to our database. + */ + /* Zero out the DBTs */ memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); - /* The key is the item's SKU */ + /* + * The key is the item's SKU. This is a unique value, so we need + * not support duplicates for this database. + */ key.data = sku; key.size = (u_int32_t)strlen(sku) + 1; diff --git a/examples/c/getting_started/example_database_read.c b/examples/c/getting_started/example_database_read.c index 79a9fc2c..0e8486ff 100644 --- a/examples/c/getting_started/example_database_read.c +++ b/examples/c/getting_started/example_database_read.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2004, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015 Oracle and/or its affiliates. All rights reserved. */ #include "gettingstarted_common.h" @@ -72,6 +72,10 @@ main(int argc, char *argv[]) return (ret); } + /* + * Show either a single item or all items, depending + * on whether itemname is set to a value. + */ if (itemname == NULL) ret = show_all_records(&my_stock); else @@ -197,23 +201,33 @@ show_inventory_item(void *vBuf) char *category, *name, *sku, *vendor_name; char *buf = (char *)vBuf; + /* Get the price. */ price = *((float *)buf); buf_pos = sizeof(float); + /* Get the quantity. */ quantity = *((int *)(buf + buf_pos)); buf_pos += sizeof(int); + /* Get the inventory item's name */ name = buf + buf_pos; buf_pos += strlen(name) + 1; + /* Get the inventory item's sku */ sku = buf + buf_pos; buf_pos += strlen(sku) + 1; + /* + * Get the category (fruits, vegetables, desserts) that this + * item belongs to. + */ category = buf + buf_pos; buf_pos += strlen(category) + 1; + /* Get the vendor's name */ vendor_name = buf + buf_pos; + /* Display all this information */ printf("name: %s\n", name); printf("\tSKU: %s\n", sku); printf("\tCategory: %s\n", category); @@ -221,6 +235,7 @@ show_inventory_item(void *vBuf) printf("\tQuantity: %i\n", quantity); printf("\tVendor:\n"); + /* Return the vendor's name */ return (vendor_name); } diff --git a/examples/c/getting_started/gettingstarted_common.c b/examples/c/getting_started/gettingstarted_common.c index 86faa1c0..f388b13d 100644 --- a/examples/c/getting_started/gettingstarted_common.c +++ b/examples/c/getting_started/gettingstarted_common.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2004, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015 Oracle and/or its affiliates. All rights reserved. */ #include "gettingstarted_common.h" @@ -49,9 +49,11 @@ get_item_name(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey) /* Opens a database */ int -open_database(DB **dbpp, const char *file_name, - const char *program_name, FILE *error_file_pointer, - int is_secondary) +open_database(DB **dbpp, /* The DB handle that we are opening */ + const char *file_name, /* The file in which the db lives */ + const char *program_name, /* Name of the program */ + FILE *error_file_pointer, + int is_secondary) { DB *dbp; /* For convenience */ u_int32_t open_flags; @@ -173,8 +175,8 @@ initialize_stockdbs(STOCK_DBS *my_stock) my_stock->inventory_dbp = NULL; my_stock->vendor_dbp = NULL; my_stock->itemname_sdbp = NULL; - my_stock->vendor_db_name = NULL; my_stock->inventory_db_name = NULL; + my_stock->vendor_db_name = NULL; my_stock->itemname_db_name = NULL; } diff --git a/examples/c/getting_started/gettingstarted_common.h b/examples/c/getting_started/gettingstarted_common.h index 7365fc7f..90c12e6e 100644 --- a/examples/c/getting_started/gettingstarted_common.h +++ b/examples/c/getting_started/gettingstarted_common.h @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2004, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015 Oracle and/or its affiliates. All rights reserved. */ #include <db.h> @@ -52,8 +52,8 @@ typedef struct vendor { } VENDOR; /* Function prototypes */ -int databases_close(STOCK_DBS *); int databases_setup(STOCK_DBS *, const char *, FILE *); +int databases_close(STOCK_DBS *); void initialize_stockdbs(STOCK_DBS *); int open_database(DB **, const char *, const char *, FILE *, int); void set_db_filenames(STOCK_DBS *my_stock); diff --git a/examples/c/txn_guide/txn_guide.c b/examples/c/txn_guide/txn_guide.c index e278120e..813244fd 100644 --- a/examples/c/txn_guide/txn_guide.c +++ b/examples/c/txn_guide/txn_guide.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/examples/c/txn_guide/txn_guide_inmemory.c b/examples/c/txn_guide/txn_guide_inmemory.c index 621bb2ae..d15397ad 100644 --- a/examples/c/txn_guide/txn_guide_inmemory.c +++ b/examples/c/txn_guide/txn_guide_inmemory.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ |