Exemple #1
0
static svn_error_t *
write_new_rep(const svn_test_opts_t *opts,
              apr_pool_t *pool)
{
  struct rep_args args;
  const char *rep = "((fulltext 0 ) a83t2Z0q)";
  svn_fs_t *fs;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_bdb_fs
          (&fs, "test-repo-write-new-rep", opts,
           pool));

  /* Set up transaction baton */
  args.fs = fs;
  args.skel = svn_skel__parse(rep, strlen(rep), pool);
  args.key = NULL;

  /* Write new rep to reps table. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_write_new_rep, &args,
                                 FALSE, pool));

  if (args.key == NULL)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error writing new representation");

  return SVN_NO_ERROR;
}
svn_error_t *
svn_fs_bdb__read_rep(representation_t **rep_p,
                     svn_fs_t *fs,
                     const char *key,
                     trail_t *trail,
                     apr_pool_t *pool)
{
  base_fs_data_t *bfd = fs->fsap_data;
  svn_skel_t *skel;
  int db_err;
  DBT query, result;

  svn_fs_base__trail_debug(trail, "representations", "get");
  db_err = bfd->representations->get(bfd->representations,
                                     trail->db_txn,
                                     svn_fs_base__str_to_dbt(&query, key),
                                     svn_fs_base__result_dbt(&result), 0);
  svn_fs_base__track_dbt(&result, 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,
       _("No such representation '%s'"), key);

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

  /* Parse the REPRESENTATION skel.  */
  skel = svn_skel__parse(result.data, result.size, pool);

  /* Convert to a native type.  */
  return svn_fs_base__parse_representation_skel(rep_p, skel, pool);
}
Exemple #3
0
static svn_error_t *
write_rep(const svn_test_opts_t *opts,
          apr_pool_t *pool)
{
  struct rep_args new_args;
  struct rep_args args;
  const char *new_rep = "((fulltext 0 ) a83t2Z0q)";
  const char *rep = "((fulltext 0 ) kfogel31337)";
  svn_fs_t *fs;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_bdb_fs
          (&fs, "test-repo-write-rep", opts,
           pool));

  /* Set up transaction baton */
  new_args.fs = fs;
  new_args.skel = svn_skel__parse(new_rep, strlen(new_rep), pool);
  new_args.key = NULL;

  /* Write new rep to reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_new_rep,
                                 &new_args, FALSE, pool));

  /* Make sure we got a valid key. */
  if (new_args.key == NULL)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error writing new representation");

  /* Set up transaction baton for re-writing reps. */
  args.fs = new_args.fs;
  args.skel = svn_skel__parse(rep, strlen(rep), pool);
  args.key = new_args.key;

  /* Overwrite first rep in reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_rep, &args,
                                 FALSE, pool));

  return SVN_NO_ERROR;
}
Exemple #4
0
static svn_error_t *
delete_rep(const svn_test_opts_t *opts,
           apr_pool_t *pool)
{
  struct rep_args new_args;
  struct rep_args delete_args;
  struct rep_args read_args;
  const char *new_rep = "((fulltext 0 ) a83t2Z0q)";
  svn_fs_t *fs;
  svn_error_t *err;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_bdb_fs
          (&fs, "test-repo-delete-rep", opts,
           pool));

  /* Set up transaction baton */
  new_args.fs = fs;
  new_args.skel = svn_skel__parse(new_rep, strlen(new_rep), pool);
  new_args.key = NULL;

  /* Write new rep to reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_new_rep,
                                 &new_args, FALSE, pool));

  /* Make sure we got a valid key. */
  if (new_args.key == NULL)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error writing new representation");

  /* Delete the rep we just wrote. */
  delete_args.fs = new_args.fs;
  delete_args.key = new_args.key;
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_delete_rep,
                                 &delete_args, FALSE, pool));

  /* Try to read the new rep back from the reps table. */
  read_args.fs = new_args.fs;
  read_args.skel = NULL;
  read_args.key = new_args.key;
  err = svn_fs_base__retry_txn(new_args.fs, txn_body_read_rep, &read_args,
                               FALSE, pool);

  /* We better have an error... */
  if ((! err) && (read_args.skel))
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error deleting representation");
  svn_error_clear(err);

  return SVN_NO_ERROR;
}
/* Parse SKEL_CSTR according to the description in USAGE_MSG. */
static svn_error_t *
extract_values_from_skel(svn_string_t **old_propval_p,
                         svn_string_t **propval_p,
                         const char *skel_cstr,
                         apr_pool_t *pool)
{
  apr_hash_t *proplist;
  svn_skel_t *skel;

  skel = svn_skel__parse(skel_cstr, strlen(skel_cstr), pool);
  SVN_ERR(svn_skel__parse_proplist(&proplist, skel, pool));
  *old_propval_p = apr_hash_get(proplist, KEY_OLD_PROPVAL, APR_HASH_KEY_STRING);
  *propval_p = apr_hash_get(proplist, KEY_NEW_PROPVAL, APR_HASH_KEY_STRING);

  return SVN_NO_ERROR;
}
Exemple #6
0
svn_error_t *
svn_fs_bdb__lock_get(svn_lock_t **lock_p,
                     svn_fs_t *fs,
                     const char *lock_token,
                     trail_t *trail,
                     apr_pool_t *pool)
{
  base_fs_data_t *bfd = fs->fsap_data;
  DBT key, value;
  int db_err;
  svn_skel_t *skel;
  svn_lock_t *lock;

  svn_fs_base__trail_debug(trail, "lock", "get");
  db_err = bfd->locks->get(bfd->locks, trail->db_txn,
                           svn_fs_base__str_to_dbt(&key, lock_token),
                           svn_fs_base__result_dbt(&value),
                           0);
  svn_fs_base__track_dbt(&value, pool);

  if (db_err == DB_NOTFOUND)
    return svn_fs_base__err_bad_lock_token(fs, lock_token);
  SVN_ERR(BDB_WRAP(fs, "reading lock", db_err));

  /* Parse TRANSACTION skel */
  skel = svn_skel__parse(value.data, value.size, pool);
  if (! skel)
    return svn_fs_base__err_corrupt_lock(fs, lock_token);

  /* Convert skel to native type. */
  SVN_ERR(svn_fs_base__parse_lock_skel(&lock, skel, pool));

  /* Possibly auto-expire the lock. */
  if (lock->expiration_date && (apr_time_now() > lock->expiration_date))
    {
      SVN_ERR(svn_fs_bdb__lock_delete(fs, lock_token, trail, pool));
      return SVN_FS__ERR_LOCK_EXPIRED(fs, lock_token);
    }

  *lock_p = lock;
  return SVN_NO_ERROR;
}
Exemple #7
0
svn_error_t *
svn_fs_bdb__get_node_revision(node_revision_t **noderev_p,
                              svn_fs_t *fs,
                              const svn_fs_id_t *id,
                              trail_t *trail,
                              apr_pool_t *pool)
{
  base_fs_data_t *bfd = fs->fsap_data;
  node_revision_t *noderev;
  svn_skel_t *skel;
  int db_err;
  DBT key, value;

  svn_fs_base__trail_debug(trail, "nodes", "get");
  db_err = bfd->nodes->get(bfd->nodes, trail->db_txn,
                           svn_fs_base__id_to_dbt(&key, id, pool),
                           svn_fs_base__result_dbt(&value),
                           0);
  svn_fs_base__track_dbt(&value, pool);

  /* If there's no such node, return an appropriately specific error.  */
  if (db_err == DB_NOTFOUND)
    return svn_fs_base__err_dangling_id(fs, id);

  /* Handle any other error conditions.  */
  SVN_ERR(BDB_WRAP(fs, N_("reading node revision"), db_err));

  /* If our caller doesn't really care about the return value here,
     just return successfully. */
  if (! noderev_p)
    return SVN_NO_ERROR;

  /* Parse and the NODE-REVISION skel.  */
  skel = svn_skel__parse(value.data, value.size, pool);

  /* Convert to a native FS type. */
  SVN_ERR(svn_fs_base__parse_node_revision_skel(&noderev, skel, pool));
  *noderev_p = noderev;
  return SVN_NO_ERROR;
}
Exemple #8
0
svn_error_t *
svn_sqlite__column_properties(apr_hash_t **props,
                              svn_sqlite__stmt_t *stmt,
                              int column,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
{
  apr_size_t len;
  const void *val;

  /* svn_skel__parse_proplist copies everything needed to result_pool */
  val = svn_sqlite__column_blob(stmt, column, &len, NULL);
  if (val == NULL)
    {
      *props = NULL;
      return SVN_NO_ERROR;
    }

  SVN_ERR(svn_skel__parse_proplist(props,
                                   svn_skel__parse(val, len, scratch_pool),
                                   result_pool));

  return SVN_NO_ERROR;
}
Exemple #9
0
svn_error_t *
svn_fs_bdb__get_copy(copy_t **copy_p,
                     svn_fs_t *fs,
                     const char *copy_id,
                     trail_t *trail,
                     apr_pool_t *pool)
{
    base_fs_data_t *bfd = fs->fsap_data;
    DBT key, value;
    int db_err;
    svn_skel_t *skel;
    copy_t *copy;

    /* Only in the context of this function do we know that the DB call
       will not attempt to modify copy_id, so the cast belongs here.  */
    svn_fs_base__trail_debug(trail, "copies", "get");
    db_err = bfd->copies->get(bfd->copies, trail->db_txn,
                              svn_fs_base__str_to_dbt(&key, copy_id),
                              svn_fs_base__result_dbt(&value),
                              0);
    svn_fs_base__track_dbt(&value, pool);

    if (db_err == DB_NOTFOUND)
        return svn_fs_base__err_no_such_copy(fs, copy_id);
    SVN_ERR(BDB_WRAP(fs, N_("reading copy"), db_err));

    /* Unparse COPY skel */
    skel = svn_skel__parse(value.data, value.size, pool);
    if (! skel)
        return svn_fs_base__err_corrupt_copy(fs, copy_id);

    /* Convert skel to native type. */
    SVN_ERR(svn_fs_base__parse_copy_skel(&copy, skel, pool));
    *copy_p = copy;
    return SVN_NO_ERROR;
}
Exemple #10
0
svn_error_t *
svn_fs_bdb__get_txn(transaction_t **txn_p,
                    svn_fs_t *fs,
                    const char *txn_name,
                    trail_t *trail,
                    apr_pool_t *pool)
{
  base_fs_data_t *bfd = fs->fsap_data;
  DBT key, value;
  int db_err;
  svn_skel_t *skel;
  transaction_t *transaction;

  /* Only in the context of this function do we know that the DB call
     will not attempt to modify txn_name, so the cast belongs here.  */
  svn_fs_base__trail_debug(trail, "transactions", "get");
  db_err = bfd->transactions->get(bfd->transactions, trail->db_txn,
                                  svn_fs_base__str_to_dbt(&key, txn_name),
                                  svn_fs_base__result_dbt(&value),
                                  0);
  svn_fs_base__track_dbt(&value, pool);

  if (db_err == DB_NOTFOUND)
    return svn_fs_base__err_no_such_txn(fs, txn_name);
  SVN_ERR(BDB_WRAP(fs, "reading transaction", db_err));

  /* Parse TRANSACTION skel */
  skel = svn_skel__parse(value.data, value.size, pool);
  if (! skel)
    return svn_fs_base__err_corrupt_txn(fs, txn_name);

  /* Convert skel to native type. */
  SVN_ERR(svn_fs_base__parse_transaction_skel(&transaction, skel, pool));
  *txn_p = transaction;
  return SVN_NO_ERROR;
}
Exemple #11
0
/* Parse a skeleton from a Subversion string.  */
static svn_skel_t *
parse_str(svn_stringbuf_t *str, apr_pool_t *pool)
{
  return svn_skel__parse(str->data, str->len, pool);
}
Exemple #12
0
svn_error_t *
svn_fs_bdb__changes_fetch_raw(apr_array_header_t **changes_p,
                              svn_fs_t *fs,
                              const char *key,
                              trail_t *trail,
                              apr_pool_t *pool)
{
  base_fs_data_t *bfd = fs->fsap_data;
  DBC *cursor;
  DBT query, result;
  int db_err = 0, db_c_err = 0;
  svn_error_t *err = SVN_NO_ERROR;
  change_t *change;
  apr_array_header_t *changes = apr_array_make(pool, 4, sizeof(change));

  /* Get a cursor on the first record matching KEY, and then loop over
     the records, adding them to the return array. */
  svn_fs_base__trail_debug(trail, "changes", "cursor");
  SVN_ERR(BDB_WRAP(fs, N_("creating cursor for reading changes"),
                   bfd->changes->cursor(bfd->changes, trail->db_txn,
                                        &cursor, 0)));

  /* Advance the cursor to the key that we're looking for. */
  svn_fs_base__str_to_dbt(&query, key);
  svn_fs_base__result_dbt(&result);
  db_err = svn_bdb_dbc_get(cursor, &query, &result, DB_SET);
  if (! db_err)
    svn_fs_base__track_dbt(&result, pool);

  while (! db_err)
    {
      svn_skel_t *result_skel;

      /* RESULT now contains a change record associated with KEY.  We
         need to parse that skel into an change_t structure ...  */
      result_skel = svn_skel__parse(result.data, result.size, pool);
      if (! result_skel)
        {
          err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                                  _("Error reading changes for key '%s'"),
                                  key);
          goto cleanup;
        }
      err = svn_fs_base__parse_change_skel(&change, result_skel, pool);
      if (err)
        goto cleanup;

      /* ... and add it to our return array.  */
      APR_ARRAY_PUSH(changes, change_t *) = change;

      /* Advance the cursor to the next record with this same KEY, and
         fetch that record. */
      svn_fs_base__result_dbt(&result);
      db_err = svn_bdb_dbc_get(cursor, &query, &result, DB_NEXT_DUP);
      if (! db_err)
        svn_fs_base__track_dbt(&result, pool);
    }

  /* If there are no (more) change records for this KEY, we're
     finished.  Just return the (possibly empty) array.  Any other
     error, however, needs to get handled appropriately.  */
  if (db_err && (db_err != DB_NOTFOUND))
    err = BDB_WRAP(fs, N_("fetching changes"), db_err);

 cleanup:
  /* Close the cursor. */
  db_c_err = svn_bdb_dbc_close(cursor);

  /* If we had an error prior to closing the cursor, return the error. */
  if (err)
    return svn_error_trace(err);

  /* If our only error thus far was when we closed the cursor, return
     that error. */
  if (db_c_err)
    SVN_ERR(BDB_WRAP(fs, N_("closing changes cursor"), db_c_err));

  /* Finally, set our return variable and get outta here. */
  *changes_p = changes;
  return SVN_NO_ERROR;
}
Exemple #13
0
svn_error_t *
svn_fs_bdb__changes_fetch(apr_hash_t **changes_p,
                          svn_fs_t *fs,
                          const char *key,
                          trail_t *trail,
                          apr_pool_t *pool)
{
  base_fs_data_t *bfd = fs->fsap_data;
  DBC *cursor;
  DBT query, result;
  int db_err = 0, db_c_err = 0;
  svn_error_t *err = SVN_NO_ERROR;
  apr_hash_t *changes = apr_hash_make(pool);
  apr_pool_t *subpool = svn_pool_create(pool);

  /* Get a cursor on the first record matching KEY, and then loop over
     the records, adding them to the return array. */
  svn_fs_base__trail_debug(trail, "changes", "cursor");
  SVN_ERR(BDB_WRAP(fs, N_("creating cursor for reading changes"),
                   bfd->changes->cursor(bfd->changes, trail->db_txn,
                                        &cursor, 0)));

  /* Advance the cursor to the key that we're looking for. */
  svn_fs_base__str_to_dbt(&query, key);
  svn_fs_base__result_dbt(&result);
  db_err = svn_bdb_dbc_get(cursor, &query, &result, DB_SET);
  if (! db_err)
    svn_fs_base__track_dbt(&result, pool);

  while (! db_err)
    {
      change_t *change;
      svn_skel_t *result_skel;

      /* Clear the per-iteration subpool. */
      svn_pool_clear(subpool);

      /* RESULT now contains a change record associated with KEY.  We
         need to parse that skel into an change_t structure ...  */
      result_skel = svn_skel__parse(result.data, result.size, subpool);
      if (! result_skel)
        {
          err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                                  _("Error reading changes for key '%s'"),
                                  key);
          goto cleanup;
        }
      err = svn_fs_base__parse_change_skel(&change, result_skel, subpool);
      if (err)
        goto cleanup;

      /* ... and merge it with our return hash.  */
      err = fold_change(changes, change);
      if (err)
        goto cleanup;

      /* Now, if our change was a deletion or replacement, we have to
         blow away any changes thus far on paths that are (or, were)
         children of this path.
         ### i won't bother with another iteration pool here -- at
             most we talking about a few extra dups of paths into what
             is already a temporary subpool.
      */
      if ((change->kind == svn_fs_path_change_delete)
          || (change->kind == svn_fs_path_change_replace))
        {
          apr_hash_index_t *hi;

          for (hi = apr_hash_first(subpool, changes);
               hi;
               hi = apr_hash_next(hi))
            {
              /* KEY is the path. */
              const void *hashkey;
              apr_ssize_t klen;
              const char *child_relpath;

              apr_hash_this(hi, &hashkey, &klen, NULL);

              /* If we come across our own path, ignore it.
                 If we come across a child of our path, remove it. */
              child_relpath = svn_fspath__skip_ancestor(change->path, hashkey);
              if (child_relpath && *child_relpath)
                apr_hash_set(changes, hashkey, klen, NULL);
            }
        }

      /* Advance the cursor to the next record with this same KEY, and
         fetch that record. */
      svn_fs_base__result_dbt(&result);
      db_err = svn_bdb_dbc_get(cursor, &query, &result, DB_NEXT_DUP);
      if (! db_err)
        svn_fs_base__track_dbt(&result, pool);
    }

  /* Destroy the per-iteration subpool. */
  svn_pool_destroy(subpool);

  /* If there are no (more) change records for this KEY, we're
     finished.  Just return the (possibly empty) array.  Any other
     error, however, needs to get handled appropriately.  */
  if (db_err && (db_err != DB_NOTFOUND))
    err = BDB_WRAP(fs, N_("fetching changes"), db_err);

 cleanup:
  /* Close the cursor. */
  db_c_err = svn_bdb_dbc_close(cursor);

  /* If we had an error prior to closing the cursor, return the error. */
  if (err)
    return svn_error_trace(err);

  /* If our only error thus far was when we closed the cursor, return
     that error. */
  if (db_c_err)
    SVN_ERR(BDB_WRAP(fs, N_("closing changes cursor"), db_c_err));

  /* Finally, set our return variable and get outta here. */
  *changes_p = changes;
  return SVN_NO_ERROR;
}
Exemple #14
0
static svn_error_t *
unparse_list(const char **msg,
             svn_boolean_t msg_only,
             svn_test_opts_t *opts,
             apr_pool_t *pool)
{
  *msg = "unparse lists";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Make a list of all the single-byte implicit-length atoms.  */
  {
    svn_stringbuf_t *str = get_empty_string(pool);
    int byte;
    svn_skel_t *list = empty(pool);
    svn_skel_t *reparsed, *elt;

    for (byte = 0; byte < 256; byte++)
      if (skel_is_name( (apr_byte_t)byte))
        {
          char buf = byte;
          add(build_atom(1, &buf, pool), list);
        }

    /* Unparse that, parse it again, and see if we got the same thing
       back.  */
    str = svn_skel__unparse(list, pool);
    reparsed = svn_skel__parse(str->data, str->len, pool);

    if (! reparsed || reparsed->is_atom)
      return fail(pool, "result is syntactically misformed, or not a list");

    if (! skel_equal(list, reparsed))
      return fail(pool, "unparsing and parsing didn't preserve contents");

    elt = reparsed->children;
    for (byte = 255; byte >= 0; byte--)
      if (skel_is_name( (apr_byte_t)byte))
        {
          if (! (elt
                 && elt->is_atom
                 && elt->len == 1
                 && elt->data[0] == byte))
            return fail(pool, "bad element");

          /* Verify that each element's data falls within the string.  */
          if (elt->data < str->data
              || elt->data + elt->len > str->data + str->len)
            return fail(pool, "bad element");

          elt = elt->next;
        }

    /* We should have reached the end of the list at this point.  */
    if (elt)
      return fail(pool, "list too long");
  }

  /* Make a list of lists.  */
  {
    svn_stringbuf_t *str = get_empty_string(pool);
    svn_skel_t *top = empty(pool);
    svn_skel_t *reparsed;
    int i;

    for (i = 0; i < 10; i++)
      {
        svn_skel_t *middle = empty(pool);
        int j;

        for (j = 0; j < 10; j++)
          {
            char buf[10];
            apr_size_t k;
            int val;

            /* Make some interesting atom, containing lots of binary
               characters.  */
            val = i * 10 + j;
            for (k = 0; k < sizeof(buf); k++)
              {
                buf[k] = val;
                val += j;
              }

            add(build_atom(sizeof(buf), buf, pool), middle);
          }

        add(middle, top);
      }

    str = svn_skel__unparse(top, pool);
    reparsed = svn_skel__parse(str->data, str->len, pool);

    if (! skel_equal(top, reparsed))
      return fail(pool, "failed to reparse list of lists");
  }

  return SVN_NO_ERROR;
}
Exemple #15
0
static svn_error_t *
read_rep(const svn_test_opts_t *opts,
         apr_pool_t *pool)
{
  struct rep_args new_args;
  struct rep_args args;
  struct rep_args read_args;
  svn_stringbuf_t *skel_data;
  svn_fs_t *fs;

  const char *rep = "((fulltext 0 ) kfogel31337)";
  const char *new_rep_before = "((fulltext 0 ) a83t2Z0)";

  /* This test also tests the introduction of checksums into skels that
     didn't have them. */

  /* Get writeable strings. */
  char *rep_after = apr_pstrdup
    (pool, "((fulltext 0  (md5 16 XXXXXXXXXXXXXXXX)) kfogel31337");
  char *new_rep_after = apr_pstrdup
    (pool, "((fulltext 0  (md5 16 XXXXXXXXXXXXXXXX)) a83t2Z0");
  size_t rep_after_len = strlen(rep_after);
  size_t new_rep_after_len = strlen(new_rep_after);

  /* Replace the fake fake checksums with the real fake checksums.
     And someday, when checksums are actually calculated, we can
     replace the real fake checksums with real real checksums. */
  {
    char *p;

    for (p = rep_after; *p; p++)
      if (*p == 'X')
        *p = '\0';

    for (p = new_rep_after; *p; p++)
      if (*p == 'X')
        *p = '\0';
  }

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_bdb_fs
          (&fs, "test-repo-read-rep", opts,
           pool));

  /* Set up transaction baton */
  new_args.fs = fs;
  new_args.skel = svn_skel__parse(new_rep_before, strlen(new_rep_before),
                                  pool);
  new_args.key = NULL;

  /* Write new rep to reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_new_rep,
                                 &new_args, FALSE, pool));

  /* Make sure we got a valid key. */
  if (new_args.key == NULL)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error writing new representation");

  /* Read the new rep back from the reps table. */
  read_args.fs = new_args.fs;
  read_args.skel = NULL;
  read_args.key = new_args.key;
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_read_rep, &read_args,
                                 FALSE, pool));

  /* Make sure the skel matches. */
  if (! read_args.skel)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error reading new representation");

  skel_data = svn_skel__unparse(read_args.skel, pool);
  if (memcmp(skel_data->data, new_rep_after, new_rep_after_len) != 0)
    return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
                             "representation corrupted (first check)");

  /* Set up transaction baton for re-writing reps. */
  args.fs = new_args.fs;
  args.skel = svn_skel__parse(rep, strlen(rep), pool);
  args.key = new_args.key;

  /* Overwrite first rep in reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_rep, &args,
                                 FALSE, pool));

  /* Read the new rep back from the reps table (using the same FS and
     key as the first read...let's make sure this thing didn't get
     written to the wrong place). */
  read_args.skel = NULL;
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_read_rep, &read_args,
                                 FALSE, pool));

  /* Make sure the skel matches. */
  if (! read_args.skel)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error reading new representation");

  skel_data = svn_skel__unparse(read_args.skel, pool);
  if (memcmp(skel_data->data, rep_after, rep_after_len) != 0)
    return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
                             "representation corrupted (second check)");

  return SVN_NO_ERROR;
}
Exemple #16
0
/* Parse a skeleton from a C string.  */
static svn_skel_t *
parse_cstr(const char *str, apr_pool_t *pool)
{
  return svn_skel__parse(str, strlen(str), pool);
}
Exemple #17
0
svn_error_t *
svn_fs_bdb__get_txn_list(apr_array_header_t **names_p,
                         svn_fs_t *fs,
                         trail_t *trail,
                         apr_pool_t *pool)
{
  base_fs_data_t *bfd = fs->fsap_data;
  apr_size_t const next_key_key_len = strlen(NEXT_KEY_KEY);
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_array_header_t *names;
  DBC *cursor;
  DBT key, value;
  int db_err, db_c_err;

  /* Allocate the initial names array */
  names = apr_array_make(pool, 4, sizeof(const char *));

  /* Create a database cursor to list the transaction names. */
  svn_fs_base__trail_debug(trail, "transactions", "cursor");
  SVN_ERR(BDB_WRAP(fs, "reading transaction list (opening cursor)",
                   bfd->transactions->cursor(bfd->transactions,
                                             trail->db_txn, &cursor, 0)));

  /* Build a null-terminated array of keys in the transactions table. */
  for (db_err = svn_bdb_dbc_get(cursor,
                                svn_fs_base__result_dbt(&key),
                                svn_fs_base__result_dbt(&value),
                                DB_FIRST);
       db_err == 0;
       db_err = svn_bdb_dbc_get(cursor,
                                svn_fs_base__result_dbt(&key),
                                svn_fs_base__result_dbt(&value),
                                DB_NEXT))
    {
      transaction_t *txn;
      svn_skel_t *txn_skel;
      svn_error_t *err;

      /* Clear the per-iteration subpool */
      svn_pool_clear(subpool);

      /* Track the memory alloc'd for fetching the key and value here
         so that when the containing pool is cleared, this memory is
         freed. */
      svn_fs_base__track_dbt(&key, subpool);
      svn_fs_base__track_dbt(&value, subpool);

      /* Ignore the "next-key" key. */
      if (key.size == next_key_key_len
          && 0 == memcmp(key.data, NEXT_KEY_KEY, next_key_key_len))
        continue;

      /* Parse TRANSACTION skel */
      txn_skel = svn_skel__parse(value.data, value.size, subpool);
      if (! txn_skel)
        {
          svn_bdb_dbc_close(cursor);
          return svn_fs_base__err_corrupt_txn
            (fs, apr_pstrmemdup(pool, key.data, key.size));
        }

      /* Convert skel to native type. */
      if ((err = svn_fs_base__parse_transaction_skel(&txn, txn_skel,
                                                     subpool)))
        {
          svn_bdb_dbc_close(cursor);
          return err;
        }

      /* If this is an immutable "committed" transaction, ignore it. */
      if (is_committed(txn))
        continue;

      /* Add the transaction name to the NAMES array, duping it into POOL. */
      APR_ARRAY_PUSH(names, const char *) = apr_pstrmemdup(pool, key.data,
                                                           key.size);
    }

  /* Check for errors, but close the cursor first. */
  db_c_err = svn_bdb_dbc_close(cursor);
  if (db_err != DB_NOTFOUND)
    {
      SVN_ERR(BDB_WRAP(fs, "reading transaction list (listing keys)",
                       db_err));
    }
  SVN_ERR(BDB_WRAP(fs, "reading transaction list (closing cursor)",
                   db_c_err));

  /* Destroy the per-iteration subpool */
  svn_pool_destroy(subpool);

  *names_p = names;
  return SVN_NO_ERROR;
}