/*
 * uri.c:
 *
 * Copyright (c) 2000 James McKenzie <james@fishsoup.dhs.org>,
 * All rights reserved.
 *
 */

static char rcsid[] =
    "$Id: work.c,v 1.7 2002/06/23 17:16:39 root Exp root $";

/*
 * $Log: work.c,v $
 * Revision 1.7  2002/06/23 17:16:39  root
 * #
 *
 * Revision 1.6  2001/10/12 13:51:11  root
 * #
 *
 * Revision 1.5  2001/10/04 18:00:36  root
 * #
 *
 * Revision 1.4  2001/01/30 06:16:18  root
 * #
 *
 * Revision 1.3  2000/12/01 04:42:10  root
 * #
 *
 * Revision 1.2  2000/11/23 23:45:19  root
 * #
 *
 * Revision 1.1  2000/10/07 18:30:03  root
 * #
 *
 * Revision 1.5  2000/09/24 01:58:26  root
 * #
 *
 * Revision 1.4  2000/09/24 01:58:21  root
 * #
 *
 * Revision 1.3  2000/09/24 01:46:04  root
 * #
 *
 * Revision 1.2  2000/09/24 01:44:47  root
 * #
 *
 * Revision 1.1  2000/09/19 03:53:27  root
 * #
 *
 */

#include "project.h"

/* Make berkley DB be praised, when they didn't add an extra */
/* function call or something - grrr.... */


#if ( DB_VERSION_MAJOR > 3 )
#define NEWDB
#else
#if ( DB_VERSION_MAJOR == 3 )
#if ( DB_VERSION_MINOR > 2 )
#define NEWDB
#endif
#endif
#endif

static DB *workdb = NULL;

/*Initialize the inode -> name database*/
static void work_init(char *name)
{
  int ret;

  if (workdb)
    return;

  ret = db_create(&workdb, NULL, 0);
  if (ret) {
    fprintf(stderr, "db_create: %s\n", db_strerror(ret));
    workdb = NULL;
    return;
  }


  ret = workdb->set_flags(workdb, DB_RECNUM);

  if (ret) {
    workdb->err(workdb, ret, "workdb");
  }

  ret = workdb->open(workdb, name, NULL, DB_BTREE, DB_CREATE, 0x600);
  if (ret) {
    workdb->err(workdb, ret, "workdb");
    workdb->close(workdb, 0);
    workdb = NULL;
  }

}

/* ensure workdb is initialized */
#define DOINIT  { if (!workdb) work_init(NULL); };


EXTERNAL int files_is_work(Eweid e)
{
  DBT key = { 0 };
  DBT data = { 0 };
  int ret;
  char *f;

  key.size = sizeof(e->e);
  key.data = e->e;

  DOINIT;

  ret = workdb->get(workdb, NULL, &key, &data, 0);

  if (ret == DB_NOTFOUND)
    return 0;

  if (ret) {
    workdb->err(workdb, ret, "DB->get");
    return 0;
  }

  return 1;
}

INTERNAL void work_remove(Eweid e)
{
  DBT key = { 0 };
  int ret;
  char *f;

  key.size = sizeof(e->e);
  key.data = e->e;

  DOINIT;

  ret = workdb->del(workdb, NULL, &key, 0);

  if (ret == DB_NOTFOUND)
    return;

  if (ret) {
    workdb->err(workdb, ret, "DB->del");
  }
}

INTERNAL void work_add(Eweid e)
{
  DBT key = { 0 };
  DBT data = { 0 };
  int ret;

  key.data = e->e;
  key.size = sizeof(e->e);

  data.data = NULL;
  data.size = 0;

  DOINIT;

#if 0
  {
    char *a = eweidtoa(e);
    printf("ADD %s\n", a);
    free(a);
  }
#endif

  ret = workdb->put(workdb, NULL, &key, &data, 0);

  if (ret) {
    workdb->err(workdb, ret, "DB->put");
  }
}

EXTERNAL int files_num_works(void)
{
  DB_BTREE_STAT *stat;
  int ret;

  DOINIT;


#ifdef NEWDB
  ret = workdb->stat(workdb, &stat, DB_RECORDCOUNT);
#else
  ret = workdb->stat(workdb, &stat, NULL, DB_RECORDCOUNT);
#endif

  if (ret) {
    workdb->err(workdb, ret, "DB->stat");
    return 0;
  }

  ret = stat->bt_nkeys;
  free(stat);
  return ret;
}

EXTERNAL Eweid files_work_by_num(int n)
{
  DBT key = { 0 };
  DBT data = { 0 };
  db_recno_t rn = (db_recno_t) n + 1;
  int ret;
  Eweid e;

  DOINIT;

  key.data = &rn;
  key.size = sizeof(rn);

  ret = workdb->get(workdb, NULL, &key, &data, DB_SET_RECNO);

  if (ret) {
    workdb->err(workdb, ret, "DB->getrecno");
  }

  if (key.size != sizeof(e->e))
    return NULL;

  e = CREATE_OBJ(Eweid);

  bcopy(key.data, e->e, key.size);

  return e;
}

EXTERNAL Eweid files_random_work(void)
{
  int n = files_num_works();
  long unsigned int i;
  Eweid ret;
  char *a;

  i = lrand48();

  if (!n) {
    fprintf(stderr, "Random - nothing to choose from\n");
    return 0;
  }

  i %= n;
  ret = files_work_by_num(i);
  a = eweidtoa(ret);
  fprintf(stderr, "Random chose %d/%d %s\n", (int) i, n, a);

  free(a);
  return ret;
}

EXTERNAL void files_work_reset(void)
{

  DOINIT;

  workdb->close(workdb, 0);
  workdb = NULL;

  DOINIT;

}


