summaryrefslogtreecommitdiff
path: root/subversion/svnfsfs/load-index-cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/svnfsfs/load-index-cmd.c')
-rw-r--r--subversion/svnfsfs/load-index-cmd.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/subversion/svnfsfs/load-index-cmd.c b/subversion/svnfsfs/load-index-cmd.c
new file mode 100644
index 0000000..4df86bd
--- /dev/null
+++ b/subversion/svnfsfs/load-index-cmd.c
@@ -0,0 +1,193 @@
+/* load-index-cmd.c -- implements the dump-index sub-command.
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include "svn_ctype.h"
+#include "svn_dirent_uri.h"
+#include "svn_io.h"
+#include "svn_pools.h"
+
+#include "private/svn_fs_fs_private.h"
+#include "private/svn_sorts_private.h"
+
+#include "svn_private_config.h"
+
+#include "svnfsfs.h"
+
+/* Map svn_fs_fs__p2l_entry_t.type to C string. */
+static const char *item_type_str[]
+ = {"none", "frep", "drep", "fprop", "dprop", "node", "chgs", "rep"};
+
+/* Reverse lookup in ITEM_TYPE_STR: Set *TYPE to the index that contains STR.
+ * Return an error for invalid strings. */
+static svn_error_t *
+str_to_item_type(unsigned *type,
+ const char *str)
+{
+ unsigned i;
+ for (i = 0; i < sizeof(item_type_str) / sizeof(item_type_str[0]); ++i)
+ if (strcmp(item_type_str[i], str) == 0)
+ {
+ *type = i;
+ return SVN_NO_ERROR;
+ }
+
+ return svn_error_createf(SVN_ERR_BAD_TOKEN, NULL,
+ _("Unknown item type '%s'"), str);
+}
+
+/* Parse the string given as const char * at IDX in TOKENS and return its
+ * value in *VALUE_P. Assume that the string an integer with base RADIX.
+ * Check for index overflows and non-hex chars.
+ */
+static svn_error_t *
+token_to_i64(apr_int64_t *value_p,
+ apr_array_header_t *tokens,
+ int idx,
+ int radix)
+{
+ const char *hex;
+ char *end;
+ apr_int64_t value;
+
+ /* Tell the user when there is not enough information. */
+ SVN_ERR_ASSERT(idx >= 0);
+ if (tokens->nelts <= idx)
+ return svn_error_createf(SVN_ERR_INVALID_INPUT, NULL,
+ _("%i columns needed, %i provided"),
+ idx + 1, tokens->nelts);
+
+ /* hex -> int conversion */
+ hex = APR_ARRAY_IDX(tokens, idx, const char *);
+ value = apr_strtoi64(hex, &end, radix);
+
+ /* Has the whole token be parsed without error? */
+ if (errno || *end != '\0')
+ return svn_error_createf(SVN_ERR_INVALID_INPUT, NULL,
+ _("%s is not a value HEX string"), hex);
+
+ *value_p = value;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the P2L entry given as space separated values in LINE and return it
+ * in *ENTRY. Ignore extra columns. Allocate the result in RESULT_POOL and
+ * use SCRATCH_POOL for temporaries.
+ */
+static svn_error_t *
+parse_index_line(svn_fs_fs__p2l_entry_t **entry,
+ svn_stringbuf_t *line,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *tokens = svn_cstring_split(line->data, " ", TRUE,
+ scratch_pool);
+ svn_fs_fs__p2l_entry_t *result = apr_pcalloc(result_pool, sizeof(*result));
+ apr_int64_t value;
+
+ /* Parse the hex columns. */
+ SVN_ERR(token_to_i64(&value, tokens, 0, 16));
+ result->offset = (apr_off_t)value;
+ SVN_ERR(token_to_i64(&value, tokens, 1, 16));
+ result->size = (apr_off_t)value;
+
+ /* Parse the rightmost colum that we care of. */
+ SVN_ERR(token_to_i64(&value, tokens, 4, 10));
+ result->item.number = (apr_uint64_t)value;
+
+ /* We now know that there were at least 5 columns.
+ * Parse the non-hex columns without index check. */
+ SVN_ERR(str_to_item_type(&result->type,
+ APR_ARRAY_IDX(tokens, 2, const char *)));
+ SVN_ERR(svn_revnum_parse(&result->item.revision,
+ APR_ARRAY_IDX(tokens, 3, const char *), NULL));
+
+ *entry = result;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the space separated P2L index table from INPUT, one entry per line.
+ * Rewrite the respective index files in PATH. Allocate from POOL. */
+static svn_error_t *
+load_index(const char *path,
+ svn_stream_t *input,
+ apr_pool_t *pool)
+{
+ svn_fs_t *fs;
+ svn_revnum_t revision = SVN_INVALID_REVNUM;
+ apr_array_header_t *entries = apr_array_make(pool, 16, sizeof(void*));
+ apr_pool_t *iterpool = svn_pool_create(pool);
+
+ /* Check repository type and open it. */
+ SVN_ERR(open_fs(&fs, path, pool));
+
+ while (TRUE)
+ {
+ svn_stringbuf_t *line;
+ svn_fs_fs__p2l_entry_t *entry;
+ svn_boolean_t eol;
+
+ /* Get the next line from the input and stop if there is none. */
+ svn_pool_clear(iterpool);
+ svn_stream_readline(input, &line, "\n", &eol, iterpool);
+ if (eol)
+ break;
+
+ /* Skip header line(s). They contain the sub-string [Ss]tart. */
+ if (strstr(line->data, "tart"))
+ continue;
+
+ /* Ignore empty lines (mostly trailing ones but we don't really care).
+ */
+ svn_stringbuf_strip_whitespace(line);
+ if (line->len == 0)
+ continue;
+
+ /* Parse the entry and append it to ENTRIES. */
+ SVN_ERR(parse_index_line(&entry, line, pool, iterpool));
+ APR_ARRAY_PUSH(entries, svn_fs_fs__p2l_entry_t *) = entry;
+
+ /* There should be at least one item that is not empty.
+ * Get a revision from (probably inside) the respective shard. */
+ if ( revision == SVN_INVALID_REVNUM
+ && entry->item.revision != SVN_INVALID_REVNUM)
+ revision = entry->item.revision;
+ }
+
+ /* Rewrite the indexes. */
+ SVN_ERR(svn_fs_fs__load_index(fs, revision, entries, iterpool));
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
+/* This implements `svn_opt_subcommand_t'. */
+svn_error_t *
+subcommand__load_index(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+ svnfsfs__opt_state *opt_state = baton;
+ svn_stream_t *input;
+
+ SVN_ERR(svn_stream_for_stdin(&input, pool));
+ SVN_ERR(load_index(opt_state->repository_path, input, pool));
+
+ return SVN_NO_ERROR;
+}