You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2010/03/01 11:29:50 UTC
svn commit: r917450 - in /subversion/trunk/subversion/libsvn_fs_base: dag.c
dag.h reps-strings.c reps-strings.h tree.c
Author: julianfoad
Date: Mon Mar 1 10:29:50 2010
New Revision: 917450
URL: http://svn.apache.org/viewvc?rev=917450&view=rev
Log:
>From Philip Martin's "obliterate-like-deltify" branch, bring in a new kind
of obliterate function which obliterates the changes made by a particular
rep. This is here to experiment with; there are no calls to it yet.
* subversion/libsvn_fs_base/dag.c,
subversion/libsvn_fs_base/dag.h
(svn_fs_base__dag_obliterate_rep): New function, renamed from the
function svn_fs_base__dag_obliterate() on the branch.
* subversion/libsvn_fs_base/reps-strings.c,
subversion/libsvn_fs_base/reps-strings.h
(svn_fs_base__rep_obliterate): New function.
* subversion/libsvn_fs_base/tree.c
(txn_obliterate_rep_args): New struct.
(txn_body_obliterate_rep, svn_fs_base__obliterate_rep): New functions.
Modified:
subversion/trunk/subversion/libsvn_fs_base/dag.c
subversion/trunk/subversion/libsvn_fs_base/dag.h
subversion/trunk/subversion/libsvn_fs_base/reps-strings.c
subversion/trunk/subversion/libsvn_fs_base/reps-strings.h
subversion/trunk/subversion/libsvn_fs_base/tree.c
Modified: subversion/trunk/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/dag.c?rev=917450&r1=917449&r2=917450&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/trunk/subversion/libsvn_fs_base/dag.c Mon Mar 1 10:29:50 2010
@@ -1530,6 +1530,33 @@
}
+svn_error_t *
+svn_fs_base__dag_obliterate_rep(dag_node_t *node,
+ dag_node_t *pred_node,
+ trail_t *trail,
+ apr_pool_t *pool)
+{
+ node_revision_t *node_rev, *pred_node_rev;
+ svn_fs_t *fs = svn_fs_base__dag_get_fs(node);
+ const char *pred_key;
+
+ SVN_ERR(svn_fs_bdb__get_node_revision(&node_rev, fs, node->id, trail, pool));
+ if (pred_node)
+ {
+ SVN_ERR(svn_fs_bdb__get_node_revision(&pred_node_rev, fs, pred_node->id,
+ trail, pool));
+ pred_key = pred_node_rev->data_key;
+ }
+ else
+ {
+ pred_key = NULL;
+ }
+
+ return svn_fs_base__rep_obliterate(trail->fs, node_rev->data_key, pred_key,
+ trail, pool);
+}
+
+
/* Maybe store a `checksum-reps' index record for the representation whose
key is REP. (If there's already a rep for this checksum, we don't
bother overwriting it.) */
Modified: subversion/trunk/subversion/libsvn_fs_base/dag.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/dag.h?rev=917450&r1=917449&r2=917450&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/dag.h (original)
+++ subversion/trunk/subversion/libsvn_fs_base/dag.h Mon Mar 1 10:29:50 2010
@@ -558,6 +558,15 @@
trail_t *trail,
apr_pool_t *pool);
+/* Obliterate NODE's data by constructing a new representation that
+ consists of a no-change delta from PRED_NODE, and changing NODE to
+ use that new rep, and leaving the old rep alone in case it is used
+ by other nodes. If PRED_NODE is null
+ then construct a representation with an empty fulltext instead. */
+svn_error_t *svn_fs_base__dag_obliterate_rep(dag_node_t *node,
+ dag_node_t *pred_node,
+ trail_t *trail,
+ apr_pool_t *pool);
/* Index NODE's backing data representations by their checksum. Do
this as part of TRAIL. Use POOL for allocations. */
Modified: subversion/trunk/subversion/libsvn_fs_base/reps-strings.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/reps-strings.c?rev=917450&r1=917449&r2=917450&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/reps-strings.c (original)
+++ subversion/trunk/subversion/libsvn_fs_base/reps-strings.c Mon Mar 1 10:29:50 2010
@@ -1621,3 +1621,132 @@
return SVN_NO_ERROR;
}
+
+svn_error_t *svn_fs_base__rep_obliterate(svn_fs_t *fs,
+ const char *key,
+ const char *pred_key,
+ trail_t *trail,
+ apr_pool_t *pool)
+{
+ const char *new_str = NULL;
+ representation_t *empty;
+ svn_stream_t *new_stream;
+ struct write_svndiff_strings_baton new_baton;
+ svn_stream_t *pred_stream1, *pred_stream2;
+ svn_txdelta_stream_t *txdelta_stream;
+ base_fs_data_t *bfd = fs->fsap_data;
+ svn_txdelta_window_handler_t new_handler;
+ void *new_handler_baton;
+ apr_pool_t *wpool;
+ apr_array_header_t *windows;
+ window_write_t *ww;
+ svn_txdelta_window_t *window;
+ svn_filesize_t tview_off = 0;
+ svn_filesize_t diffsize = 0;
+ const unsigned char *digest;
+ representation_t *pred_rep;
+ representation_t new_rep;
+ rep_delta_chunk_t *chunk;
+ apr_array_header_t *chunks;
+ int i;
+
+ if (!pred_key)
+ {
+ /* No predecessor so just write a new empty rep */
+ SVN_ERR(svn_fs_bdb__string_append(fs, &new_str, 0, NULL, trail, pool));
+ empty = make_fulltext_rep(new_str, NULL,
+ svn_checksum_empty_checksum(svn_checksum_md5,
+ pool),
+ svn_checksum_empty_checksum(svn_checksum_sha1,
+ pool),
+ pool);
+ SVN_ERR(svn_fs_bdb__write_rep(fs, key, empty, trail, pool));
+
+ return SVN_NO_ERROR;
+ }
+
+ if (!strcmp(key, pred_key))
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ _("Attempt to obliterate '%s' using itself "),
+ key);
+
+ new_baton.fs = fs;
+ new_baton.trail = trail;
+ new_baton.header_read = FALSE;
+ new_stream = svn_stream_create(&new_baton, pool);
+ svn_stream_set_write(new_stream, write_svndiff_strings);
+
+ /* ### Is there a simpler way to write a no-change delta? */
+ SVN_ERR(svn_fs_base__rep_contents_read_stream(&pred_stream1, fs, pred_key,
+ TRUE, trail, pool));
+ SVN_ERR(svn_fs_base__rep_contents_read_stream(&pred_stream2, fs, pred_key,
+ TRUE, trail, pool));
+ svn_txdelta(&txdelta_stream, pred_stream1, pred_stream2, pool);
+
+ if (bfd->format >= SVN_FS_BASE__MIN_SVNDIFF1_FORMAT)
+ svn_txdelta_to_svndiff2(&new_handler, &new_handler_baton,
+ new_stream, 1, pool);
+ else
+ svn_txdelta_to_svndiff2(&new_handler, &new_handler_baton,
+ new_stream, 0, pool);
+
+ wpool = svn_pool_create(pool);
+ windows = apr_array_make(pool, 1, sizeof(ww));
+ do
+ {
+ new_baton.size = 0;
+ new_baton.key = NULL;
+ svn_pool_clear(wpool);
+
+ SVN_ERR(svn_txdelta_next_window(&window, txdelta_stream, wpool));
+ SVN_ERR(new_handler(window, new_handler_baton));
+ if (window)
+ {
+ ww = apr_pcalloc(pool, sizeof(*ww));
+ ww->key = new_baton.key;
+ ww->svndiff_len = new_baton.size;
+ ww->text_off = tview_off;
+ ww->text_len = window->tview_len;
+ APR_ARRAY_PUSH(windows, window_write_t *) = ww;
+ tview_off += window->tview_len;
+ diffsize += ww->svndiff_len;
+ }
+ } while (window);
+
+ svn_pool_destroy(wpool);
+
+ digest = svn_txdelta_md5_digest(txdelta_stream);
+ if (!digest)
+ return svn_error_createf(SVN_ERR_DELTA_MD5_CHECKSUM_ABSENT, NULL,
+ _("Failed to calculate MD5 digest for '%s'"),
+ pred_key);
+ /* ### Check the digest against something? pred_rep->md5_checksum? */
+
+ SVN_ERR(svn_fs_bdb__read_rep(&pred_rep, fs, pred_key, trail, pool));
+ new_rep.md5_checksum = svn_checksum_dup(pred_rep->md5_checksum, pool);
+ new_rep.sha1_checksum = svn_checksum_dup(pred_rep->sha1_checksum, pool);
+ new_rep.kind = rep_kind_delta;
+ new_rep.txn_id = NULL;
+
+ chunks = apr_array_make(pool, windows->nelts, sizeof(chunk));
+
+ for (i = 0; i < windows->nelts; i++)
+ {
+ ww = APR_ARRAY_IDX(windows, i, window_write_t *);
+
+ chunk = apr_palloc(pool, sizeof(*chunk));
+ chunk->offset = ww->text_off;
+
+ chunk->version = new_baton.version;
+ chunk->string_key = ww->key;
+ chunk->size = ww->text_len;
+ chunk->rep_key = pred_key;
+
+ APR_ARRAY_PUSH(chunks, rep_delta_chunk_t *) = chunk;
+ }
+
+ new_rep.contents.delta.chunks = chunks;
+ SVN_ERR(svn_fs_bdb__write_rep(fs, key, &new_rep, trail, pool));
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/trunk/subversion/libsvn_fs_base/reps-strings.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/reps-strings.h?rev=917450&r1=917449&r2=917450&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/reps-strings.h (original)
+++ subversion/trunk/subversion/libsvn_fs_base/reps-strings.h Mon Mar 1 10:29:50 2010
@@ -168,6 +168,18 @@
trail_t *trail,
apr_pool_t *pool);
+/* Obliterate KEY's data by creating a new rep that consists of a
+ no-change delta from PRED_KEY's data. If PRED_KEY is null then
+ construct an empty fulltext instead of a delta. KEY's old data
+ remains in the database in case some other key's data is derived
+ from it. */
+/* ### TODO: clarify. What kind of objects are KEY and PRED_KEY, and what
+ does it do with the new rep? */
+svn_error_t *svn_fs_base__rep_obliterate(svn_fs_t *fs,
+ const char *key,
+ const char *pred_key,
+ trail_t *trail,
+ apr_pool_t *pool);
#ifdef __cplusplus
Modified: subversion/trunk/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/tree.c?rev=917450&r1=917449&r2=917450&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/trunk/subversion/libsvn_fs_base/tree.c Mon Mar 1 10:29:50 2010
@@ -2940,6 +2940,94 @@
}
+struct txn_obliterate_rep_args
+{
+ const svn_fs_id_t *id;
+ svn_boolean_t has_pred;
+ const svn_fs_id_t *pred_id;
+};
+
+static svn_error_t *
+txn_body_obliterate_rep(void *baton, trail_t *trail)
+{
+ struct txn_obliterate_rep_args *args = baton;
+ dag_node_t *node, *pred_node;
+
+ SVN_ERR(svn_fs_base__dag_get_node(&node, trail->fs, args->id,
+ trail, trail->pool));
+ if (args->has_pred)
+ {
+ SVN_ERR(svn_fs_base__dag_get_node(&pred_node, trail->fs, args->pred_id,
+ trail, trail->pool));
+ }
+ else
+ {
+ pred_node = NULL;
+ }
+
+ SVN_ERR(svn_fs_base__dag_obliterate_rep(node, pred_node, trail, trail->pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_base__obliterate_rep(svn_fs_t *fs,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *pool)
+{
+ svn_fs_root_t *root;
+ const char *txn_id;
+ struct rev_get_txn_id_args get_txn_args;
+ const svn_fs_id_t *id;
+ svn_node_kind_t kind;
+ struct txn_pred_count_args pred_count_args;
+ struct txn_obliterate_rep_args oblit_args;
+
+ SVN_ERR(svn_fs_base__revision_root(&root, fs, revision, pool));
+ get_txn_args.txn_id = &txn_id;
+ get_txn_args.revision = revision;
+ SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_rev_get_txn_id, &get_txn_args,
+ FALSE, pool));
+
+ SVN_ERR(base_node_id(&id, root, path, pool));
+ if (strcmp(svn_fs_base__id_txn_id(id), txn_id))
+ return svn_error_createf(SVN_ERR_FS_NOT_MUTABLE, NULL,
+ _("Unexpected immutable node at '%s'"), path);
+
+ SVN_ERR(base_check_path(&kind, root, path, pool));
+ if (kind != svn_node_file)
+ return svn_error_createf(SVN_ERR_FS_NOT_FILE, NULL,
+ _("Cannot obliterate '%s' as it is not a file"),
+ path);
+
+ pred_count_args.id = id;
+ SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_pred_count, &pred_count_args,
+ FALSE, pool));
+
+ if (pred_count_args.pred_count > 0)
+ {
+ struct txn_pred_id_args pred_id_args;
+
+ pred_id_args.id = id;
+ pred_id_args.pool = pool;
+ SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_pred_id, &pred_id_args,
+ FALSE, pool));
+
+ oblit_args.has_pred = TRUE;
+ oblit_args.pred_id = pred_id_args.pred_id;
+ }
+ else
+ {
+ oblit_args.has_pred = FALSE;
+ }
+ oblit_args.id = id;
+
+ return svn_fs_base__retry_txn(fs, txn_body_obliterate_rep, &oblit_args,
+ TRUE, pool);
+}
+
+
/* Modifying directories */