/* strings-table.c : operations on the `strings' 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 "strings-table.h"
#include "key-gen.h"
#include "svn_pools.h"

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

int
svn_fs__open_strings_table (DB **strings_p,
                            DB_ENV *env,
                            int create)
{
  DB *strings;

  DB_ERR (db_create (&strings, env, 0));

  /* Enable duplicate keys. This allows the data to be spread out across
     multiple records. Note: this must occur before ->open().  */
  DB_ERR (strings->set_flags (strings, DB_DUP));

  DB_ERR (strings->open (strings, "strings", 0, DB_BTREE,
                       create ? (DB_CREATE | DB_EXCL) : 0,
                       0666));

  if (create)
  {
    DBT key, value;

    /* Create the `next-key' table entry.  */
    DB_ERR (strings->put
            (strings, 0,
             svn_fs__str_to_dbt (&key, (char *) svn_fs__next_key_key),
             svn_fs__str_to_dbt (&value, (char *) "0"),
             0));
  }
  
  *strings_p = strings;
  return 0;
}



/*** Storing and retrieving strings.  ***/

static svn_error_t *
locate_key (apr_size_t *length,
            DBC **cursor,
            DBT *query,
            svn_fs_t *fs,
            trail_t *trail)
{
  int db_err;
  DBT result;

  SVN_ERR (DB_WRAP (fs, "creating cursor for reading a string",
                    fs->strings->cursor (fs->strings, trail->db_txn,
                                         cursor, 0)));

  /* Set up the DBT for reading the length of the record. */
  svn_fs__clear_dbt (&result);
  result.ulen = 0;
  result.flags |= DB_DBT_USERMEM;

  /* Advance the cursor to the key that we're looking for. */
  db_err = (*cursor)->c_get (*cursor, query, &result, DB_SET);

  /* We don't need to svn_fs__track_dbt() the result, because nothing
     was allocated in it. */

  /* If there's no such node, return an appropriately specific error.  */
  if (db_err == DB_NOTFOUND)
    {
      (*cursor)->c_close (*cursor);
      return svn_error_createf
        (SVN_ERR_FS_NO_SUCH_STRING, 0, 0, fs->pool,
         "locate_key: no such string `%s'", (const char *)query->data);
    }
  if (db_err)
    {
      DBT rerun;

      if (db_err != ENOMEM)
        {
          (*cursor)->c_close (*cursor);
          return DB_WRAP (fs, "could not move cursor", db_err);
        }

      /* We got an ENOMEM (typical since we have a zero length buf), so
         we need to re-run the operation to make it happen. */
      svn_fs__clear_dbt (&rerun);
      rerun.flags |= DB_DBT_USERMEM | DB_DBT_PARTIAL;
      SVN_ERR (DB_WRAP (fs, "rerunning cursor move",
                        (*cursor)->c_get (*cursor, query, &rerun, DB_SET)));
    }

  /* ### this cast might not be safe? */
  *length = (apr_size_t) result.size;

  return SVN_NO_ERROR;
}

static int
get_next_length (apr_size_t *length, DBC *cursor, DBT *query)
{
  DBT result;
  int db_err;

  /* Set up the DBT for reading the length of the record. */
  svn_fs__clear_dbt (&result);
  result.ulen = 0;
  result.flags |= DB_DBT_USERMEM;

  /* Note: this may change the QUERY DBT, but that's okay: we're going
     to be sticking with the same key anyways.  */
  db_err = cursor->c_get (cursor, query, &result, DB_NEXT_DUP);

  /* Note that we exit on DB_NOTFOUND. The caller uses that to end a loop. */
  if (db_err)
    {
      DBT rerun;

      if (db_err != ENOMEM)
        {
          cursor->c_close (cursor);
          return db_err;
        }

      /* We got an ENOMEM (typical since we have a zero length buf), so
         we need to re-run the operation to make it happen. */
      svn_fs__clear_dbt (&rerun);
      rerun.flags |= DB_DBT_USERMEM | DB_DBT_PARTIAL;
      db_err = cursor->c_get (cursor, query, &rerun, DB_NEXT_DUP);
    }

  /* ### this cast might not be safe? */
  *length = (apr_size_t) result.size;
  return db_err;
}


/* Read *LEN bytes into BUF from OFFSET in string KEY in FS, as part
 * of TRAIL.
 * 
 * On return, *LEN is set to the number of bytes read. This value may
 * be less than the number requested.
 *
 * If OFFSET is past the end of the string, then *LEN will be set to
 * zero. Callers which are advancing OFFSET as they read portions of
 * the string can terminate their loop when *LEN is returned as zero
 * (which will occur when OFFSET == length(the string)).
 * 
 * If string KEY does not exist, the error SVN_ERR_FS_NO_SUCH_STRING
 * is returned.
 */
static svn_error_t *
string_read (svn_fs_t *fs,
             const char *key,
             char *buf,
             apr_off_t offset,
             apr_size_t *len,
             trail_t *trail)
{
  int db_err;
  DBT query, result;
  DBC *cursor;
  apr_size_t length;

  svn_fs__str_to_dbt (&query, (char *) key);

  SVN_ERR (locate_key (&length, &cursor, &query, fs, trail));

  /* Seek through the records for this key, trying to find the record that
     includes OFFSET. Note that we don't require reading from more than
     one record since we're allowed to return partial reads.  */
  while (length <= offset)
    {
      offset -= length;

      db_err = get_next_length (&length, cursor, &query);

      /* No more records? They tried to read past the end. */
      if (db_err == DB_NOTFOUND)
        {
          *len = 0;
          return SVN_NO_ERROR;
        }
      if (db_err)
        return DB_WRAP (fs, "reading string", db_err);
    }

  /* The current record contains OFFSET. Fetch the contents now. Note that
     OFFSET has been moved to be relative to this record. The length could
     quite easily extend past this record, but no big deal. We also keep
     the DB_DBT_PARTIAL to read little pieces at this location.  */
  svn_fs__clear_dbt (&result);
  result.data = buf;
  result.ulen = *len;
  result.doff = offset;
  result.dlen = *len;
  result.flags |= (DB_DBT_USERMEM | DB_DBT_PARTIAL);
  db_err = cursor->c_get (cursor, &query, &result, DB_CURRENT);
  if (db_err)
    goto cursor_error;

  /* Done with the cursor. */
  SVN_ERR (DB_WRAP (fs, "closing string-reading cursor",
                    cursor->c_close (cursor)));

  *len = result.size;
  return SVN_NO_ERROR;

cursor_error:
  /* An error occurred somewhere. Close the cursor and return the error. */
  cursor->c_close (cursor);
  return DB_WRAP (fs, "reading string", db_err);
}


svn_error_t *
svn_fs__string_read (svn_fs_t *fs,
                     const char *key,
                     char *buf,
                     apr_off_t offset,
                     apr_size_t *len,
                     trail_t *trail)
{
  apr_size_t amt_read = 0;

  /* ### todo: See IZ issue #642.

     Currently, the helper function for this, string_read() is having
     to lookup keys and setup the cursor on each call.  Ideally, the
     following looping concept would be inside that helper so would
     only have to setup the cursor once. */
  while (1)
    {
      apr_size_t size = *len - amt_read;
      SVN_ERR (string_read (fs, key, buf + amt_read, offset + amt_read, 
                            &size, trail));
      amt_read += size;
      if ((size == 0) || (amt_read == *len))
        break;
    }
  
  *len = amt_read;
  return SVN_NO_ERROR;
}


/* Get the current 'next-key' value and bump the record. */
static svn_error_t *
get_key_and_bump (svn_fs_t *fs, const char **key, trail_t *trail)
{
  DBC *cursor;
  char next_key[200];
  apr_size_t key_len;
  int db_err;
  DBT query;
  DBT result;

  /* ### todo: see issue #409 for why bumping the key as part of this
     trail is problematic. */

  /* Open a cursor and move it to the 'next-key' value. We can then fetch
     the contents and use the cursor to overwrite those contents. Since
     this database allows duplicates, we can't do an arbitrary 'put' to
     write the new value -- that would append, not overwrite.  */

  SVN_ERR (DB_WRAP (fs, "creating cursor for reading a string",
                    fs->strings->cursor (fs->strings, trail->db_txn,
                                         &cursor, 0)));

  /* Advance the cursor to 'next-key' and read it. */

  db_err = cursor->c_get (cursor,
                          svn_fs__str_to_dbt (&query,
                                              (char *) svn_fs__next_key_key),
                          svn_fs__result_dbt (&result),
                          DB_SET);
  if (db_err)
    {
      cursor->c_close (cursor);
      return DB_WRAP (fs, "getting next-key value", db_err);
    }

  svn_fs__track_dbt (&result, trail->pool);
  *key = apr_pstrndup (trail->pool, result.data, result.size);

  /* Bump to future key. */
  key_len = result.size;
  svn_fs__next_key (result.data, &key_len, next_key);

  /* Shove the new key back into the database, at the cursor position. */
  db_err = cursor->c_put (cursor, &query,
                          svn_fs__str_to_dbt (&result, (char *) next_key),
                          DB_CURRENT);

  cursor->c_close (cursor);

  return DB_WRAP (fs, "bumping next string key", db_err);
}

svn_error_t *
svn_fs__string_append (svn_fs_t *fs,
                       const char **key,
                       apr_size_t len,
                       const char *buf,
                       trail_t *trail)
{
  DBT query, result;

  /* If the passed-in key is NULL, we graciously generate a new string
     using the value of the `next-key' record in the strings table. */
  if (*key == NULL)
    {
      SVN_ERR (get_key_and_bump (fs, key, trail));
    }

  /* Store a new record into the database. */
  SVN_ERR (DB_WRAP (fs, "appending string",
                    fs->strings->put
                    (fs->strings, trail->db_txn,
                     svn_fs__str_to_dbt (&query, (char *) (*key)),
                     svn_fs__set_dbt (&result, (void *) buf, len),
                     0)));

  return SVN_NO_ERROR;
}


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

  svn_fs__str_to_dbt (&query, (char *)key);

  /* Torch the prior contents */
  db_err = fs->strings->del (fs->strings, trail->db_txn, &query, 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_STRING, 0, 0, fs->pool,
       "svn_fs__string_clear: no such string `%s'", key);

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

  /* Shove empty data back in for this key. */
  svn_fs__clear_dbt (&result);
  result.data = 0;
  result.size = 0;
  result.flags |= DB_DBT_USERMEM;

  return DB_WRAP (fs, "storing empty contents",
                  fs->strings->put (fs->strings, trail->db_txn,
                                    &query, &result, 0));
}


svn_error_t *
svn_fs__string_size (apr_size_t *size,
                     svn_fs_t *fs,
                     const char *key,
                     trail_t *trail)
{
  int db_err;
  DBT query;
  DBC *cursor;
  apr_size_t length;
  apr_size_t total;

  svn_fs__str_to_dbt (&query, (char *) key);

  SVN_ERR (locate_key (&length, &cursor, &query, fs, trail));

  total = length;
  while (1)
    {
      db_err = get_next_length (&length, cursor, &query);

      /* No more records? Then return the total length. */
      if (db_err == DB_NOTFOUND)
        {
          *size = total;
          return SVN_NO_ERROR;
        }
      if (db_err)
        return DB_WRAP (fs, "fetching string length", db_err);

      total += length;
    }

  /* NOTREACHED */
}


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

  db_err = fs->strings->del (fs->strings, 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_STRING, 0, 0, fs->pool,
       "svn_fs__delete_string: no such string `%s'", key);

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

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs__string_copy (svn_fs_t *fs,
                     const char **new_key,
                     const char *key,
                     trail_t *trail)
{
  DBT query;
  DBT result;
  DBT copykey;
  DBC *cursor;
  int db_err;

  SVN_ERR (get_key_and_bump (fs, new_key, trail));

  SVN_ERR (DB_WRAP (fs, "creating cursor for reading a string",
                    fs->strings->cursor (fs->strings, trail->db_txn,
                                         &cursor, 0)));

  svn_fs__str_to_dbt (&query, (char *) key);
  svn_fs__str_to_dbt (&copykey, (char *) *new_key);

  svn_fs__clear_dbt (&result);

  /* Move to the first record and fetch its data (under BDB's mem mgmt). */
  db_err = cursor->c_get (cursor, &query, &result, DB_SET);
  if (db_err)
    {
      cursor->c_close (cursor);
      return DB_WRAP (fs, "getting next-key value", db_err);
    }

  while (1)
    {
      /* ### can we pass a BDB-provided buffer to another BDB function?
         ### they are supposed to have a duration up to certain points
         ### of calling back into BDB, but I'm not sure what the exact
         ### rules are. it is definitely nicer to use BDB buffers here
         ### to simplify things and reduce copies, but... hrm.
      */

      /* Write the data to the database */
      db_err = fs->strings->put (fs->strings, trail->db_txn,
                                 &copykey, &result, 0);
      if (db_err)
        {
          cursor->c_close (cursor);
          return DB_WRAP (fs, "writing copied data", db_err);
        }

      /* Read the next chunk. Terminate loop if we're done. */
      svn_fs__clear_dbt (&result);
      db_err = cursor->c_get (cursor, &query, &result, DB_NEXT_DUP);
      if (db_err == DB_NOTFOUND)
        break;
      if (db_err)
        {
          cursor->c_close (cursor);
          return DB_WRAP (fs, "fetching string data for a copy", db_err);
        }
    }

  cursor->c_close (cursor);

  return SVN_NO_ERROR;
}


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