Not logged in

Artifact 999b2278aa1cb633522a6b72a4715a2a47a779dd:


/* zdbi.c

   Copyright © 2016 Brandon Invergo <brandon@invergo.net>

   This file is part of zeptodb

   zeptodb is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   zeptodb is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with zeptodb.  If not, see <http://www.gnu.org/licenses/>.
*/

#define _GNU_SOURCE

#include <config.h>
#include <string.h>
#include "error.h"
#include "argp.h"
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include "zdb.h"

const char *program_name = "zdbi";
const char *argp_program_version = PACKAGE_STRING;
const char *argp_program_bug_address = PACKAGE_BUGREPORT;
static void *database;
static char doc[] =
  "zdbi -- inspect a DBM database";
static char args_doc[] = "DATABASE";

static struct argp_option options[] = {
  {"mmap-size",   (int)'m', "NUM", 0,
   "The size (in bytes) of the memory-mapped region to use (default=1024)", 0},
  {"cache-size", (int)'c', "NUM", 0,
   "The bucket cache size to use (default=128)", 0},
  {"block-size", (int)'b', "NUM", 0,
   "The block size to use (default=512)", 0},
  {"no-mmap", (int)'n', (const char *)NULL, 0,
   "Do not memory-map the database file", 0},
  {"no-lock", (int)'l', (const char *)NULL, 0,
   "Do not perform any locking of the database file", 0},
  {"verbose", (int)'v', (const char *)NULL, 0,
   "Print extra information.", 0},
  {(const char *)NULL, 0, (const char *)NULL, 0, (const char *)NULL, 0}
};

struct arguments
{
  char *args[1];
  size_t mmap_size;
  size_t cache_size;
  size_t block_size;
  bool no_mmap;
  bool no_lock;
  bool verbose;
};

static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
  struct arguments *arguments = state->input;
  unsigned long int size;
  switch (key)
    {
    case 'b':
      size = arg ? strtoul (arg, NULL, 10) : 512UL;
      if (size > SIZE_MAX)
        {
          arguments->cache_size = SIZE_MAX;
        }
      else
        {
          arguments->cache_size = (size_t)size;
        }
      break;
    case 'c':
      size = arg ? strtoul (arg, NULL, 10) : 128UL;
      if (size > SIZE_MAX)
        {
          arguments->cache_size = SIZE_MAX;
        }
      else
        {
          arguments->cache_size = (size_t)size;
        }
      break;
    case 'l':
      arguments->no_lock = true;
      break;
    case 'm':
      size = arg ? strtoul (arg, NULL, 10) : 131072UL;
      if (size > SIZE_MAX)
        {
          arguments->mmap_size = SIZE_MAX;
        }
      else
        {
          arguments->mmap_size = (size_t)size;
        }
      break;
    case 'n':
      arguments->no_mmap = true;
      break;
    case 'v':
      arguments->verbose = true;
      break;
    case ARGP_KEY_ARG:
      if (state->arg_num >= 1)
        argp_usage (state);
      arguments->args[state->arg_num] = arg;
      break;
    case ARGP_KEY_END:
      if (state->arg_num == 0)
        argp_usage (state);
      break;
    default:
      return ARGP_ERR_UNKNOWN;
    }
  return 0;
}

static struct argp argp = {options, parse_opt, args_doc, doc,
                           (const struct argp_child *)NULL,
                           NULL, (const char *)NULL};

static void
termination_handler (int signum __attribute__ ((unused)))
{
  printf ("Interrupt caught, closing database\n");
  if (database && zdb_close (database, false))
    error (EXIT_FAILURE, errno, "Failed to close database");
  else
    exit (EXIT_SUCCESS);
}

int
main (int argc, char **argv)
{
  struct arguments arguments;
  int mode = ZDB_READER;
  error_t argp_result;

  arguments.mmap_size = 1024;
  arguments.cache_size = 128;
  arguments.block_size = 512;
  arguments.no_mmap = false;
  arguments.no_lock = false;
  arguments.verbose = false;

  argp_result = argp_parse (&argp, argc, argv, 0, 0, &arguments);
  if (argp_result)
    error (EXIT_FAILURE, argp_result, "Failed to parse arguments");

  if (signal (SIGINT, termination_handler) == SIG_IGN)
    signal (SIGINT, SIG_IGN);
  if (signal (SIGHUP, termination_handler) == SIG_IGN)
    signal (SIGHUP, SIG_IGN);
  if (signal (SIGTERM, termination_handler) == SIG_IGN)
    signal (SIGTERM, SIG_IGN);

  if (arguments.no_lock)
    mode ^= ZDB_NOLOCK;
  if (arguments.no_mmap)
    mode ^= ZDB_NOMMAP;

  /* open the database */
  database = zdb_open (arguments.args[0], mode, arguments.mmap_size,
                       arguments.cache_size, arguments.block_size,
                       arguments.verbose);
  if (!database)
    error (EXIT_FAILURE, errno,
           "Failed to open database %s", arguments.args[0]);
  zdb_print_info (database);
  if (zdb_close (database, arguments.verbose) != 0)
    error (EXIT_FAILURE, errno,
           "Failed to close database %s", arguments.args[0]);
  exit (EXIT_SUCCESS);
}