aboutsummaryrefslogtreecommitdiff
path: root/src/fetchkeys.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fetchkeys.c')
-rw-r--r--src/fetchkeys.c320
1 files changed, 320 insertions, 0 deletions
diff --git a/src/fetchkeys.c b/src/fetchkeys.c
new file mode 100644
index 0000000..32f0199
--- /dev/null
+++ b/src/fetchkeys.c
@@ -0,0 +1,320 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <gdbm.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+static unsigned long
+get_size (char const *str)
+{
+ char *p;
+ unsigned long n, m;
+
+ errno = 0;
+ n = strtoul (str, &p, 10);
+ if (errno)
+ {
+ perror (str);
+ exit (1);
+ }
+ switch (*p)
+ {
+ case 0:
+ m = 1;
+ break;
+
+ case 'k':
+ case 'K':
+ p++;
+ m = 1024;
+ break;
+
+ case 'm':
+ case 'M':
+ p++;
+ m = 1024 * 1024;
+ break;
+ }
+
+ if (*p)
+ {
+ fprintf (stderr, "%s: bad number (near %s)\n", str, p);
+ exit (1);
+ }
+
+ if (ULONG_MAX / m < n)
+ {
+ fprintf (stderr, "%s: number too big\n", str);
+ exit (1);
+ }
+ return m * n;
+}
+
+#ifdef DUMPSTATS
+static void
+dump_stats (GDBM_FILE dbf, size_t n)
+{
+ static size_t cache_size;
+ static struct gdbm_cache_stat *stat;
+ size_t access_count, cache_count;
+ FILE *fp;
+ char fname[80];
+ size_t i;
+
+ if (cache_size == 0)
+ {
+ if (gdbm_setopt (dbf, GDBM_GETCACHESIZE, &cache_size, sizeof(cache_size)))
+ {
+ fprintf (stderr, "GDBM_GETCACHESIZE: %s\n",
+ gdbm_strerror (gdbm_errno));
+ exit (1);
+ }
+ stat = calloc (cache_size, sizeof (stat[0]));
+ assert (stat != NULL);
+ }
+
+ gdbm_get_cache_stats (dbf, &access_count, &cache_count, stat, cache_size);
+
+ snprintf (fname, sizeof (fname), "%zu.stat", n);
+
+ fp = fopen (fname, "w");
+ assert (fp != NULL);
+
+ fprintf (fp, "%zu\n", access_count);
+ fprintf (fp, "%zu\n", cache_count);
+ for (i = 0; i < cache_count; i++)
+ {
+ fprintf (fp, "%zu %zu\n", stat[i].adr, stat[i].hits);
+ }
+ fclose (fp);
+
+ fprintf (stderr, "%80.80s\rDump file %s\n", "", fname);
+}
+
+static volatile int statsig;
+
+void
+sighan (int sig)
+{
+ statsig = 1;
+ signal (sig, sighan);
+}
+#endif
+
+char *dbname = "a.gdbm";
+char *kfname = "keys.txt";
+int percent;
+int verbose = 0;
+int time_verbose = 1;
+
+char *keybuf;
+char *keyptr;
+char *keyend;
+size_t nkeys;
+
+char *
+nextkey (void)
+{
+ char *ret = keyptr;
+
+ if (keyptr >= keyend)
+ return NULL;
+ keyptr += strlen (keyptr) + 1;
+ return ret;
+}
+
+void
+readkeys (char const *name)
+{
+ FILE *fp;
+ size_t n;
+ struct stat st;
+ char *p;
+
+ if (stat (name, &st))
+ {
+ fprintf (stderr, "%s: can't stat: %s\n", name, strerror (errno));
+ exit (1);
+ }
+
+ fp = fopen (name, "r");
+ if (!fp)
+ {
+ fprintf (stderr, "%s: can't read: %s\n", name, strerror (errno));
+ exit (1);
+ }
+
+ keybuf = malloc (st.st_size + 1);
+ assert (keybuf != NULL);
+ keyend = keybuf + st.st_size;
+ *keyend = 0;
+
+ if (fread (keybuf, st.st_size, 1, fp) != 1)
+ {
+ fprintf (stderr, "%s: read error: %s\n", name, strerror (errno));
+ exit (1);
+ }
+ fclose (fp);
+ keyptr = keybuf;
+
+ nkeys = 0;
+ for (p = keybuf; p < keyend; p++)
+ if (*p == '\n')
+ {
+ *p = 0;
+ nkeys++;
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ GDBM_FILE dbf;
+ datum key;
+ datum data;
+ int status = 0;
+ int i;
+ int print = 0;
+ unsigned long maxsize = 0;
+ int flags = 0;
+ struct timeval t_start, t_open, t_now, td;
+ char *keystr;
+
+ while ((i = getopt (argc, argv, "c:t:nTpv")) != EOF)
+ {
+ switch (i)
+ {
+ case 'n':
+ flags |= GDBM_NOMMAP;
+ break;
+
+ case 'p':
+ print = 1;
+ break;
+
+ case 'c':
+ maxsize = get_size (optarg);
+ break;
+
+ case 'T':
+ time_verbose = 0;
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ default:
+ exit (1);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ switch (argc)
+ {
+ case 2:
+ kfname = argv[1];
+ case 1:
+ dbname = argv[0];
+ break;
+ case 0:
+ break;
+ default:
+ fprintf (stderr, "too many arguments\n");
+ exit (1);
+ }
+
+ if (verbose)
+ printf ("PID %u\n", getpid ());
+
+#ifdef DUMPSTATS
+ signal (SIGUSR1, sighan);
+#endif
+
+ gettimeofday (&t_start, NULL);
+ dbf = gdbm_open (dbname, 0, GDBM_READER | flags, 00664, NULL);
+ assert (dbf != NULL);
+ gettimeofday (&t_open, NULL);
+
+ if (maxsize)
+ {
+ int rc = gdbm_setopt (dbf, GDBM_SETCACHESIZE, &maxsize, sizeof (maxsize));
+ if (rc)
+ {
+ fprintf (stderr, "GDBM_SETCACHESIZE: %s\n", gdbm_strerror (gdbm_errno));
+ return 1;
+ }
+ }
+
+ readkeys (kfname);
+ i = 0;
+ while ((keystr = nextkey ()) != NULL)
+ {
+ i++;
+
+ if (verbose)
+ {
+ unsigned long long k = (unsigned long long) i * 100 / nkeys;
+ gettimeofday (&t_now, NULL);
+ timersub (&t_now, &t_start, &td);
+ printf ("%8u %6zu / %6zu % 2d%%\r", td.tv_sec, i, nkeys, k);
+ fflush (stdout);
+ }
+
+#ifdef DUMPSTATS
+ if (statsig)
+ {
+ dump_stats (dbf, i);
+ statsig = 0;
+ }
+#endif
+
+ key.dptr = keystr;
+ key.dsize = strlen (key.dptr);
+ data = gdbm_fetch (dbf, key);
+ if (data.dptr == NULL)
+ {
+ status = 2;
+ if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
+ {
+ fprintf (stderr, "%s: not found\n", keystr);
+ }
+ else
+ {
+ fprintf (stderr, "%s: error: %s\n", keystr,
+ gdbm_strerror (gdbm_errno));
+ }
+ continue;
+ }
+ if (print)
+ printf ("%s: %*.*s\n", keystr, data.dsize, data.dsize, data.dptr);
+ free (data.dptr);
+ }
+ gdbm_close (dbf);
+ if (verbose)
+ putchar ('\n');
+ if (time_verbose)
+ {
+ gettimeofday (&t_now, NULL);
+ timersub (&t_now, &t_start, &td);
+ printf ("%lu.%06lu\n", td.tv_sec, td.tv_usec);
+ timersub (&t_open, &t_start, &td);
+ printf ("%lu.%06lu\n", td.tv_sec, td.tv_usec);
+ timersub (&t_now, &t_open, &td);
+ printf ("%lu.%06lu\n", td.tv_sec, td.tv_usec);
+ }
+ return status;
+}
+
+
+
+
+

Return to:

Send suggestions and report system problems to the System administrator.