<commit_before>/* rep-sharing.c --- the rep-sharing cache for fsfs
 *
 * ====================================================================
 * Copyright (c) 2008 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 "svn_private_config.h"

#include "fs.h"
#include "rep-cache.h"
#include "../libsvn_fs/fs-loader.h"

#include "svn_path.h"

#include "private/svn_sqlite.h"

/* A few magic values */
#define REP_CACHE_SCHEMA_FORMAT   1

static const char * const upgrade_sql[] = { NULL,
  "pragma auto_vacuum = 1;"
  APR_EOL_STR
  "create table rep_cache (hash text not null primary key,   "
  "                        revision integer not null,        "
  "                        offset integer not null,          "
  "                        size integer not null,            "
  "                        expanded_size integer not null);  "
  APR_EOL_STR
  };


/* APR cleanup function used to close the database when destroying the FS pool
   DATA should be the FS to to which this database belongs. */
static apr_status_t
cleanup_db_apr(void *data)
{
  svn_fs_t *fs = data;
  fs_fs_data_t *ffd = fs->fsap_data;
  svn_error_t *err;
  int i;

  svn_sqlite__stmt_t *stmts[] = { ffd->rep_cache.get_rep_stmt,
                                  ffd->rep_cache.set_rep_stmt,
                                  ffd->rep_cache.inc_select_stmt,
                                  ffd->rep_cache.inc_update_stmt };

  for (i = 0; i < 4; i++)
    {
      if (stmts[i])
        {
          err = svn_sqlite__finalize(stmts[i]);
          if (err)
            goto err_cleanup;
        }
    }

  err = svn_sqlite__close(ffd->rep_cache.db, SVN_NO_ERROR);
  if (err)
    goto err_cleanup;

  return APR_SUCCESS;

  err_cleanup:
    fs->warning(fs->warning_baton, err);
    svn_error_clear(err);

    return SVN_ERR_FS_CLEANUP;
}


svn_error_t *
svn_fs_fs__open_rep_cache(svn_fs_t *fs,
                          apr_pool_t *pool)
{
  fs_fs_data_t *ffd = fs->fsap_data;
  const char *db_path;

  /* Open (or create) the sqlite database */
  db_path = svn_path_join(fs->path, REP_CACHE_DB_NAME, pool);
  SVN_ERR(svn_sqlite__open(&ffd->rep_cache.db, db_path,
                           svn_sqlite__mode_rwcreate, REP_CACHE_SCHEMA_FORMAT,
                           upgrade_sql, fs->pool, pool));

  apr_pool_cleanup_register(fs->pool, fs, cleanup_db_apr,
                            apr_pool_cleanup_null);

  return SVN_NO_ERROR;
}

svn_error_t *
svn_fs_fs__get_rep_reference(representation_t **rep,
                             svn_fs_t *fs,
                             svn_checksum_t *checksum,
                             apr_pool_t *pool)
{
  fs_fs_data_t *ffd = fs->fsap_data;
  svn_boolean_t have_row;

  if (ffd->rep_cache.db == NULL)
    {
      *rep = NULL;
      return SVN_NO_ERROR;
    }

  /* We only allow SHA1 checksums in this table. */
  if (checksum->kind != svn_checksum_sha1)
    return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL,
                            _("Only SHA1 checksums can be used as keys in the "
                              "rep_cache table.\n"));

  if (!ffd->rep_cache.get_rep_stmt)
    SVN_ERR(svn_sqlite__prepare(&ffd->rep_cache.get_rep_stmt, ffd->rep_cache.db,
                  "select revision, offset, size, expanded_size from rep_cache "
                  "where hash = :1", fs->pool));

  SVN_ERR(svn_sqlite__bind_text(ffd->rep_cache.get_rep_stmt, 1,
                                svn_checksum_to_cstring(checksum, pool)));

  SVN_ERR(svn_sqlite__step(&have_row, ffd->rep_cache.get_rep_stmt));
  if (have_row)
    {
      *rep = apr_pcalloc(pool, sizeof(**rep));
      (*rep)->sha1_checksum = svn_checksum_dup(checksum, pool);
      (*rep)->revision = svn_sqlite__column_revnum(ffd->rep_cache.get_rep_stmt,
                                                   0);
      (*rep)->offset = svn_sqlite__column_int(ffd->rep_cache.get_rep_stmt, 1);
      (*rep)->size = svn_sqlite__column_int(ffd->rep_cache.get_rep_stmt, 2);
      (*rep)->expanded_size = svn_sqlite__column_int(ffd->rep_cache.get_rep_stmt,
                                                     3);
    }
  else
    *rep = NULL;

  return svn_sqlite__reset(ffd->rep_cache.get_rep_stmt);
}

svn_error_t *
svn_fs_fs__set_rep_reference(svn_fs_t *fs,
                             representation_t *rep,
                             svn_boolean_t reject_dup,
                             apr_pool_t *pool)
{
  fs_fs_data_t *ffd = fs->fsap_data;
  svn_boolean_t have_row;
  representation_t *old_rep;

  if (ffd->rep_cache.db == NULL)
    return SVN_NO_ERROR;

  /* We only allow SHA1 checksums in this table. */
  if (rep->sha1_checksum == NULL
        || svn_checksum_to_cstring(rep->sha1_checksum, pool) == NULL)
    return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL,
                            _("Only SHA1 checksums can be used as keys in the "
                              "rep_cache table.\n"));

  /* Check to see if we already have a mapping for REP->SHA1_CHECKSUM.  If so,
     and the value is the same one we were about to write, that's
     cool -- just do nothing.  If, however, the value is *different*,
     that's a red flag!  */
  SVN_ERR(svn_fs_fs__get_rep_reference(&old_rep, fs, rep->sha1_checksum, pool));

  if (old_rep)
    {
      if ( reject_dup && ((old_rep->revision != rep->revision)
            || (old_rep->offset != rep->offset)
            || (old_rep->size != rep->size)
            || (old_rep->expanded_size != rep->expanded_size)) )
        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                 apr_psprintf(pool,
                              _("Representation key for checksum '%%s' exists "
                                "in filesystem '%%s', with different value "
                                "(%%ld,%%%s,%%%s,%%%s) than what we were about"
                                " to store(%%ld,%%%s,%%%s,%%%s)"),
                              APR_OFF_T_FMT, SVN_FILESIZE_T_FMT,
                              SVN_FILESIZE_T_FMT, APR_OFF_T_FMT,
                              SVN_FILESIZE_T_FMT, SVN_FILESIZE_T_FMT),
                 svn_checksum_to_cstring_display(rep->sha1_checksum, pool),
                 fs->path, old_rep->revision, old_rep->offset, old_rep->size,
                 old_rep->expanded_size, rep->revision, rep->offset, rep->size,
                 rep->expanded_size);
      else
        return SVN_NO_ERROR;
    }

  if (!ffd->rep_cache.set_rep_stmt)
    SVN_ERR(svn_sqlite__prepare(&ffd->rep_cache.set_rep_stmt, ffd->rep_cache.db,
                  "insert into rep_cache (hash, revision, offset, size, "
                  "expanded_size) "
                  "values (:1, :2, :3, :4, :5);", fs->pool));

  SVN_ERR(svn_sqlite__bind_text(ffd->rep_cache.set_rep_stmt, 1,
                                svn_checksum_to_cstring(rep->sha1_checksum,
                                                        pool)));
  SVN_ERR(svn_sqlite__bind_int64(ffd->rep_cache.set_rep_stmt, 2, rep->revision));
  SVN_ERR(svn_sqlite__bind_int64(ffd->rep_cache.set_rep_stmt, 3, rep->offset));
  SVN_ERR(svn_sqlite__bind_int64(ffd->rep_cache.set_rep_stmt, 4, rep->size));
  SVN_ERR(svn_sqlite__bind_int64(ffd->rep_cache.set_rep_stmt, 5,
                                 rep->expanded_size));

  SVN_ERR(svn_sqlite__step(&have_row, ffd->rep_cache.set_rep_stmt));
  return svn_sqlite__reset(ffd->rep_cache.set_rep_stmt);
}
<commit_msg>Revert r34938, which r34941 has now made obsolete.<commit_after>/* rep-sharing.c --- the rep-sharing cache for fsfs
 *
 * ====================================================================
 * Copyright (c) 2008 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 "svn_private_config.h"

#include "fs.h"
#include "rep-cache.h"
#include "../libsvn_fs/fs-loader.h"

#include "svn_path.h"

#include "private/svn_sqlite.h"

/* A few magic values */
#define REP_CACHE_SCHEMA_FORMAT   1

static const char * const upgrade_sql[] = { NULL,
  "pragma auto_vacuum = 1;"
  APR_EOL_STR
  "create table rep_cache (hash text not null primary key,   "
  "                        revision integer not null,        "
  "                        offset integer not null,          "
  "                        size integer not null,            "
  "                        expanded_size integer not null);  "
  APR_EOL_STR
  };


/* APR cleanup function used to close the database when destroying the FS pool
   DATA should be the FS to to which this database belongs. */
static apr_status_t
cleanup_db_apr(void *data)
{
  svn_fs_t *fs = data;
  fs_fs_data_t *ffd = fs->fsap_data;
  svn_error_t *err;
  int i;

  svn_sqlite__stmt_t *stmts[] = { ffd->rep_cache.get_rep_stmt,
                                  ffd->rep_cache.set_rep_stmt,
                                  ffd->rep_cache.inc_select_stmt,
                                  ffd->rep_cache.inc_update_stmt };

  for (i = 0; i < 4; i++)
    {
      if (stmts[i])
        {
          err = svn_sqlite__finalize(stmts[i]);
          if (err)
            goto err_cleanup;
        }
    }

  err = svn_sqlite__close(ffd->rep_cache.db, SVN_NO_ERROR);
  if (err)
    goto err_cleanup;

  return APR_SUCCESS;

  err_cleanup:
    fs->warning(fs->warning_baton, err);
    svn_error_clear(err);

    return SVN_ERR_FS_CLEANUP;
}


svn_error_t *
svn_fs_fs__open_rep_cache(svn_fs_t *fs,
                          apr_pool_t *pool)
{
  fs_fs_data_t *ffd = fs->fsap_data;
  const char *db_path;

  /* Open (or create) the sqlite database */
  db_path = svn_path_join(fs->path, REP_CACHE_DB_NAME, pool);
  SVN_ERR(svn_sqlite__open(&ffd->rep_cache.db, db_path,
                           svn_sqlite__mode_rwcreate, REP_CACHE_SCHEMA_FORMAT,
                           upgrade_sql, fs->pool, pool));

  apr_pool_cleanup_register(fs->pool, fs, cleanup_db_apr,
                            apr_pool_cleanup_null);

  return SVN_NO_ERROR;
}

svn_error_t *
svn_fs_fs__get_rep_reference(representation_t **rep,
                             svn_fs_t *fs,
                             svn_checksum_t *checksum,
                             apr_pool_t *pool)
{
  fs_fs_data_t *ffd = fs->fsap_data;
  svn_boolean_t have_row;

  if (ffd->rep_cache.db == NULL)
    {
      *rep = NULL;
      return SVN_NO_ERROR;
    }

  /* We only allow SHA1 checksums in this table. */
  if (checksum->kind != svn_checksum_sha1)
    return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL,
                            _("Only SHA1 checksums can be used as keys in the "
                              "rep_cache table.\n"));

  if (!ffd->rep_cache.get_rep_stmt)
    SVN_ERR(svn_sqlite__prepare(&ffd->rep_cache.get_rep_stmt, ffd->rep_cache.db,
                  "select revision, offset, size, expanded_size from rep_cache "
                  "where hash = :1", fs->pool));

  SVN_ERR(svn_sqlite__bind_text(ffd->rep_cache.get_rep_stmt, 1,
                                svn_checksum_to_cstring(checksum, pool)));

  SVN_ERR(svn_sqlite__step(&have_row, ffd->rep_cache.get_rep_stmt));
  if (have_row)
    {
      *rep = apr_pcalloc(pool, sizeof(**rep));
      (*rep)->sha1_checksum = svn_checksum_dup(checksum, pool);
      (*rep)->revision = svn_sqlite__column_revnum(ffd->rep_cache.get_rep_stmt,
                                                   0);
      (*rep)->offset = svn_sqlite__column_int(ffd->rep_cache.get_rep_stmt, 1);
      (*rep)->size = svn_sqlite__column_int(ffd->rep_cache.get_rep_stmt, 2);
      (*rep)->expanded_size = svn_sqlite__column_int(ffd->rep_cache.get_rep_stmt,
                                                     3);
    }
  else
    *rep = NULL;

  return svn_sqlite__reset(ffd->rep_cache.get_rep_stmt);
}

svn_error_t *
svn_fs_fs__set_rep_reference(svn_fs_t *fs,
                             representation_t *rep,
                             svn_boolean_t reject_dup,
                             apr_pool_t *pool)
{
  fs_fs_data_t *ffd = fs->fsap_data;
  svn_boolean_t have_row;
  representation_t *old_rep;

  if (ffd->rep_cache.db == NULL)
    return SVN_NO_ERROR;

  /* We only allow SHA1 checksums in this table. */
  if (rep->sha1_checksum == NULL)
    return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL,
                            _("Only SHA1 checksums can be used as keys in the "
                              "rep_cache table.\n"));

  /* Check to see if we already have a mapping for REP->SHA1_CHECKSUM.  If so,
     and the value is the same one we were about to write, that's
     cool -- just do nothing.  If, however, the value is *different*,
     that's a red flag!  */
  SVN_ERR(svn_fs_fs__get_rep_reference(&old_rep, fs, rep->sha1_checksum, pool));

  if (old_rep)
    {
      if ( reject_dup && ((old_rep->revision != rep->revision)
            || (old_rep->offset != rep->offset)
            || (old_rep->size != rep->size)
            || (old_rep->expanded_size != rep->expanded_size)) )
        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                 apr_psprintf(pool,
                              _("Representation key for checksum '%%s' exists "
                                "in filesystem '%%s', with different value "
                                "(%%ld,%%%s,%%%s,%%%s) than what we were about"
                                " to store(%%ld,%%%s,%%%s,%%%s)"),
                              APR_OFF_T_FMT, SVN_FILESIZE_T_FMT,
                              SVN_FILESIZE_T_FMT, APR_OFF_T_FMT,
                              SVN_FILESIZE_T_FMT, SVN_FILESIZE_T_FMT),
                 svn_checksum_to_cstring_display(rep->sha1_checksum, pool),
                 fs->path, old_rep->revision, old_rep->offset, old_rep->size,
                 old_rep->expanded_size, rep->revision, rep->offset, rep->size,
                 rep->expanded_size);
      else
        return SVN_NO_ERROR;
    }

  if (!ffd->rep_cache.set_rep_stmt)
    SVN_ERR(svn_sqlite__prepare(&ffd->rep_cache.set_rep_stmt, ffd->rep_cache.db,
                  "insert into rep_cache (hash, revision, offset, size, "
                  "expanded_size) "
                  "values (:1, :2, :3, :4, :5);", fs->pool));

  SVN_ERR(svn_sqlite__bind_text(ffd->rep_cache.set_rep_stmt, 1,
                                svn_checksum_to_cstring(rep->sha1_checksum,
                                                        pool)));
  SVN_ERR(svn_sqlite__bind_int64(ffd->rep_cache.set_rep_stmt, 2, rep->revision));
  SVN_ERR(svn_sqlite__bind_int64(ffd->rep_cache.set_rep_stmt, 3, rep->offset));
  SVN_ERR(svn_sqlite__bind_int64(ffd->rep_cache.set_rep_stmt, 4, rep->size));
  SVN_ERR(svn_sqlite__bind_int64(ffd->rep_cache.set_rep_stmt, 5,
                                 rep->expanded_size));

  SVN_ERR(svn_sqlite__step(&have_row, ffd->rep_cache.set_rep_stmt));
  return svn_sqlite__reset(ffd->rep_cache.set_rep_stmt);
}

{'fraction_non_alphanumeric': 0.12072649572649573, 'fraction_numerical': 0.006221719457013574, 'mean_word_length': 2.1845107064238545, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 146, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5778508', 'n_tokens_mistral': 5510, 'n_tokens_neox': 5336, 'n_words': 1058}