/* reps-table.c : operations on the `representations' table
 *
 * ====================================================================
 * Copyright (c) 2000-2002 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 */

#include "db.h"
#include "svn_fs.h"
#include "fs.h"
#include "err.h"
#include "dbt.h"
#include "trail.h"
#include "reps-table.h"
#include "strings-table.h"
#include "key-gen.h"



/*** Creating and opening the representations table. ***/

int
svn_fs__open_reps_table (DB **reps_p,
                         DB_ENV *env,
                         int create)
{
  DB *reps;

  DB_ERR (db_create (&reps, env, 0));
  DB_ERR (reps->open (reps, "representations", 0, DB_BTREE,
                      create ? (DB_CREATE | DB_EXCL) : 0,
                      0666));

  /* Create the `next-key' table entry.  */
  if (create)
  {
    DBT key, value;

    DB_ERR (reps->put
            (reps, 0,
             svn_fs__str_to_dbt (&key, (char *) svn_fs__next_key_key),
             svn_fs__str_to_dbt (&value, (char *) "0"),
             0));
  }

  *reps_p = reps;
  return 0;
}



/*** Storing and retrieving reps.  ***/

svn_error_t *
svn_fs__read_rep (skel_t **skel_p,
                  svn_fs_t *fs,
                  const char *key,
                  trail_t *trail)
{
  skel_t *skel;
  int db_err;
  DBT query, result;

  db_err = fs->representations->get
    (fs->representations,
     trail->db_txn,
     svn_fs__str_to_dbt (&query, (char *) key),
     svn_fs__result_dbt (&result), 0);

  svn_fs__track_dbt (&result, trail->pool);

  /* If there's no such node, return an appropriately specific error.  */
  if (db_err == DB_NOTFOUND)
    return svn_error_createf
      (SVN_ERR_FS_NO_SUCH_REPRESENTATION, 0, 0, fs->pool,
       "svn_fs__read_rep: no such representation `%s'", key);

  /* Handle any other error conditions.  */
  SVN_ERR (DB_WRAP (fs, "reading representation", db_err));

  /* Parse the REPRESENTATION skel.  */
  skel = svn_fs__parse_skel (result.data, result.size, trail->pool);
  *skel_p = skel;

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs__write_rep (svn_fs_t *fs,
                   const char *key,
                   skel_t *skel,
                   trail_t *trail)
{
  DBT query, result;

  SVN_ERR (DB_WRAP (fs, "storing representation",
                    fs->representations->put
                    (fs->representations, trail->db_txn,
                     svn_fs__str_to_dbt (&query, (char *) key),
                     svn_fs__skel_to_dbt (&result, skel, trail->pool), 0)));

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs__write_new_rep (const char **key,
                       svn_fs_t *fs,
                       skel_t *skel,
                       trail_t *trail)
{
  DBT query, result;
  int db_err;
  apr_size_t len;
  char next_key[200];    /* This will be a problem if the number of
                            representations in a filesystem ever
                            exceeds 1821797716821872825139468712408937
                            126733897152817476066745969754933395997209
                            053270030282678007662838673314795994559163
                            674524215744560596468010549540621501770423
                            499988699078859474399479617124840673097380
                            736524850563115569208508785942830080999927
                            310762507339484047393505519345657439796788
                            24151197232629947748581376.  Somebody warn
                            my grandchildren. */
  
  /* ### todo: see issue #409 for why bumping the key as part of this
     trail is problematic. */

  /* Get the current value associated with `next-key'.  */
  svn_fs__str_to_dbt (&query, (char *) svn_fs__next_key_key);
  SVN_ERR (DB_WRAP (fs, "allocating new representation (getting next-key)",
                    fs->representations->get (fs->representations,
                                              trail->db_txn,
                                              &query,
                                              svn_fs__result_dbt (&result),
                                              0)));

  svn_fs__track_dbt (&result, trail->pool);

  /* Store the new rep skel. */
  *key = apr_pstrndup (trail->pool, result.data, result.size);
  SVN_ERR (svn_fs__write_rep (fs, *key, skel, trail));

  /* Bump to future key. */
  len = result.size;
  svn_fs__next_key (result.data, &len, next_key);
  db_err = fs->representations->put
    (fs->representations, trail->db_txn,
     svn_fs__str_to_dbt (&query, (char *) svn_fs__next_key_key),
     svn_fs__str_to_dbt (&result, (char *) next_key),
     0);

  SVN_ERR (DB_WRAP (fs, "bumping next representation key", db_err));

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs__delete_rep (svn_fs_t *fs, const char *key, trail_t *trail)
{
  int db_err;
  DBT query;

  db_err = fs->representations->del
    (fs->representations, trail->db_txn,
     svn_fs__str_to_dbt (&query, (char *) key), 0);

  /* If there's no such node, return an appropriately specific error.  */
  if (db_err == DB_NOTFOUND)
    return svn_error_createf
      (SVN_ERR_FS_NO_SUCH_REPRESENTATION, 0, 0, fs->pool,
       "svn_fs__delete_rep: no such representation `%s'", key);

  /* Handle any other error conditions.  */
  SVN_ERR (DB_WRAP (fs, "deleting representation", db_err));

  return SVN_NO_ERROR;
}



/* 
 * local variables:
 * eval: (load-file "../../tools/dev/svn-dev.el")
 * end:
 */

