wilde: utils/admin validate-skiplist.c,NONE,1.1

cvs at intevation.de cvs at intevation.de
Sun Mar 26 01:24:40 CET 2006


Author: wilde

Update of /kolabrepository/utils/admin
In directory doto:/tmp/cvs-serv2207

Added Files:
	validate-skiplist.c 
Log Message:
New file validate-skiplist.c -- a simple cyrus skiplist validator.

--- NEW FILE: validate-skiplist.c ---
/* -------------------------------------------------------------------
   validate-skiplist

   Copyright (C) 2006 by Sascha Wilde <wilde at sha-bang.de>

   This program is free software under the GNU GPL (>=v2)
   Read the file COPYING coming with the software for details.
   -------------------------------------------------------------------

   This little tool does a simple syntactic evaluation on cyrus
   skiplist database files.

   It does no semantic checking, no log replay, and _no_ locking (so
   don't use it on files used by a running system.)

   WARNING:

   This is only tested on little endian systems and will most likely
   break on big endian machines!

*/

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <err.h>

#define INFO(blk) if (verbose) { blk }
#define WARN(blk) if (warnings) { blk }

int verbose  = 0;
int warnings = 0;


/* skiplist stuff: */
#define MAGICNUM 0xa1028b0d
#define INORDER 1
#define ADD 2
#define DELETE 4
#define COMMIT 255
#define DUMMY 257

/* statistics */
int inorder = 0;
int add = 0;
int delete = 0;
int commit = 0;

void
print_usage ()
{
  puts ("Usage: validate-skiplist [OPTIONS] [FILE]");
  puts ("Validate cyrus skiplist FILE.\n");

  puts ("  -w  print out non fatal warnings");
  puts ("  -v  be verbose");
  puts ("  -h  print this help message and exit");
  exit (0);
}


int32_t
read_word (FILE *file)
{
  int i, c;
  int32_t word = 0;
  for (i = 0; i < 4; i++)
    {
      word = word << 8;
      if ((c = fgetc (file)) == EOF)
	errx (1, "Unexpected end of file at 0x%X", ftell (file));
      word += c;
    }
  return word;
}

void
jump_to_position (FILE *file, long pos)
{
  if (fseek (file, pos, SEEK_SET) == -1)
    errx (1, "Unexpected end of file at 0x%X", ftell (file));
}


void
commit_maybe (FILE *file)
{
  if (read_word (file) == COMMIT)
    {
      ++commit;
    }
  else
    fseek (file, -4, SEEK_CUR);
}


void
add_delete (FILE *file)
{
  int32_t word;
  word = read_word (file);
  switch (word)
    {
    case ADD:
      /* FIXME: we should inspect add nodes more in depth. */
      while (read_word (file) != 0xffffffff) /* skip till termination */
      ++add;
      break;
    case DELETE:
      read_word (file);
      ++delete;
      break;
    default:
      errx (1, "Bad node: expected ADD or DELETE at 0x%X! (found %i)", 
	    ftell (file), word);
    }
  commit_maybe (file);
}


void
validate_file (char* filename)
{
  int i,c;
  int32_t word;
  long logstart;
  FILE *file;

  INFO (printf ("Checking file \"%s\"\n", filename););

  if (!(file = fopen (filename, "r")))
    err (1, "%s", filename);

  WARN (word = read_word (file); /* magic number */
	if (word != MAGICNUM)
	  printf ("Strange magic number %X expected %X\n", word, MAGICNUM);
	);

  INFO (jump_to_position (file, 20); /* jump to version numbers */
	printf ("Skiplist file Version %i.", read_word (file));
	printf ("%i\n", read_word (file));
	printf ("Max level: %i\n", read_word (file));
	printf ("Current level: %i\n", read_word (file));
	printf ("%i active items\n", read_word (file));
	);

  jump_to_position (file, 40);
  logstart = read_word (file);

  INFO (printf ("Log start at 0x%X\n", logstart);
	word = read_word (file);
	printf ("Last recovery on %s\n", ctime (&word));
	);

  jump_to_position (file, 48);
  if ((word = read_word (file)) != DUMMY)
    errx (1, "First skipnode is not of type DUMMY (found %i)\n", word);

  jump_to_position (file, logstart);
  INFO (puts ("Checking log part..."););

  while ((c = getc (file)) != EOF)
    {
      ungetc (c, file);
      add_delete (file);
    } 

  INFO (printf ("Found %i ADD, %i DELETE and %i COMMIT nodes in log.\n",
		add, delete, commit);
	);

  fclose (file);
}


int
main (int argc, char** argv)
{
  int c;

  while ((c = getopt (argc, argv, "hvw")) != -1)
    switch (c)
      {
      case 'h':
	print_usage ();
	break;
      case 'v':
	verbose = 1;
	break;
      case 'w':
	warnings = 1;
	break;
      default:
	exit (1);
      }

  if (optind == (argc - 1))
    validate_file (argv[optind]);
  else
    errx (1, "Missing filename.");

  exit (0);
}





More information about the commits mailing list