1
1
/* dag.c : DAG-like interface filesystem, private to libsvn_fs
3
3
* ====================================================================
4
* Copyright (c) 2000-2006, 2008 CollabNet. All rights reserved.
6
* This software is licensed as described in the file COPYING, which
7
* you should have received as part of this distribution. The terms
8
* are also available at http://subversion.tigris.org/license-1.html.
9
* If newer versions of this license are posted there, you may use a
10
* newer version instead, at your option.
12
* This software consists of voluntary contributions made by many
13
* individuals. For exact contribution history, see the revision
14
* history and logs, available at http://subversion.tigris.org/.
4
* Licensed to the Apache Software Foundation (ASF) under one
5
* or more contributor license agreements. See the NOTICE file
6
* distributed with this work for additional information
7
* regarding copyright ownership. The ASF licenses this file
8
* to you under the Apache License, Version 2.0 (the
9
* "License"); you may not use this file except in compliance
10
* with the License. You may obtain a copy of the License at
12
* http://www.apache.org/licenses/LICENSE-2.0
14
* Unless required by applicable law or agreed to in writing,
15
* software distributed under the License is distributed on an
16
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
* KIND, either express or implied. See the License for the
18
* specific language governing permissions and limitations
15
20
* ====================================================================
1058
svn_fs_fs__dag_dup_for_cache(void **out,
1062
dag_node_t *in_node = in, *out_node;
1063
out_node = svn_fs_fs__dag_dup(in_node, pool);
1064
out_node->fs = NULL;
1066
return SVN_NO_ERROR;
1069
/* The cache serialization format is:
1071
* - For mutable nodes: the character 'M', then 'F' for files or 'D'
1072
* for directories, then the ID, then '\n', then the created path.
1074
* - For immutable nodes: the character 'I' followed by the noderev
1075
* hash dump (the other fields can be reconstructed from this). (We
1076
* assume that, once constructed, immutable nodes always contain
1081
1073
svn_fs_fs__dag_serialize(char **data,
1082
1074
apr_size_t *data_len,
1084
1076
apr_pool_t *pool)
1086
1078
dag_node_t *node = in;
1087
svn_stringbuf_t *buf = svn_stringbuf_create("", pool);
1089
if (svn_fs_fs__dag_check_mutable(node))
1091
svn_stringbuf_appendcstr(buf, "M");
1092
svn_stringbuf_appendcstr(buf, (node->kind == svn_node_file ? "F" : "D"));
1093
svn_stringbuf_appendcstr(buf, svn_fs_fs__id_unparse(node->id,
1095
svn_stringbuf_appendcstr(buf, "\n");
1096
svn_stringbuf_appendcstr(buf, node->created_path);
1079
svn_stringbuf_t *serialized;
1081
/* create an serialization context and serialize the dag node as root */
1082
svn_temp_serializer__context_t *context =
1083
svn_temp_serializer__init(node,
1088
/* for mutable nodes, we will _never_ cache the noderev */
1089
if (node->node_revision && !svn_fs_fs__dag_check_mutable(node))
1090
svn_fs_fs__noderev_serialize(context, &node->node_revision);
1100
fs_fs_data_t *ffd = node->fs->fsap_data;
1101
svn_stringbuf_appendcstr(buf, "I");
1102
SVN_ERR(svn_fs_fs__write_noderev(svn_stream_from_stringbuf(buf, pool),
1103
node->node_revision, ffd->format,
1108
*data_len = buf->len;
1092
svn_temp_serializer__set_null(context,
1093
(const void * const *)&node->node_revision);
1095
/* serialize other sub-structures */
1096
svn_fs_fs__id_serialize(context, (const svn_fs_id_t **)&node->id);
1097
svn_fs_fs__id_serialize(context, &node->fresh_root_predecessor_id);
1098
svn_temp_serializer__add_string(context, &node->created_path);
1100
/* return serialized data */
1101
serialized = svn_temp_serializer__get(context);
1102
*data = serialized->data;
1103
*data_len = serialized->len;
1109
1105
return SVN_NO_ERROR;
1113
1109
svn_fs_fs__dag_deserialize(void **out,
1115
1111
apr_size_t data_len,
1116
1112
apr_pool_t *pool)
1118
dag_node_t *node = apr_pcalloc(pool, sizeof(*node));
1114
dag_node_t *node = (dag_node_t *)data;
1120
1115
if (data_len == 0)
1121
1116
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
1122
1117
_("Empty noderev in cache"));
1126
const char *newline;
1131
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
1132
_("Kindless noderev in cache"));
1134
node->kind = svn_node_file;
1135
else if (*data == 'D')
1136
node->kind = svn_node_dir;
1138
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
1139
_("Unknown kind for noderev in cache: '%c'"),
1143
newline = memchr(data, '\n', data_len);
1145
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
1146
_("Unterminated ID in cache"));
1147
id_len = newline - 1 - data;
1148
node->id = svn_fs_fs__id_parse(data, id_len, pool);
1150
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
1151
_("Bogus ID '%s' in cache"),
1152
apr_pstrndup(pool, data, id_len));
1154
data += id_len; data_len -= id_len;
1157
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
1158
_("No created path"));
1159
node->created_path = apr_pstrndup(pool, data, data_len);
1161
else if (*data == 'I')
1163
node_revision_t *noderev;
1164
apr_pool_t *subpool = svn_pool_create(pool);
1165
svn_stream_t *stream =
1166
svn_stream_from_stringbuf(svn_stringbuf_ncreate(data + 1,
1170
SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, pool));
1171
node->kind = noderev->kind;
1172
node->id = svn_fs_fs__id_copy(noderev->id, pool);
1173
node->created_path = apr_pstrdup(pool, noderev->created_path);
1175
if (noderev->is_fresh_txn_root)
1176
node->fresh_root_predecessor_id = noderev->predecessor_id;
1178
node->node_revision = noderev;
1180
svn_pool_destroy(subpool);
1183
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
1184
_("Unknown node type in cache: '%c'"), *data);
1119
/* Copy the _full_ buffer as it also contains the sub-structures. */
1122
/* fixup all references to sub-structures */
1123
svn_fs_fs__id_deserialize(node, &node->id);
1124
svn_fs_fs__id_deserialize(node,
1125
(svn_fs_id_t **)&node->fresh_root_predecessor_id);
1126
svn_fs_fs__noderev_deserialize(node, &node->node_revision);
1128
svn_temp_deserializer__resolve(node, (void**)&node->created_path);
1188
1133
return SVN_NO_ERROR;
1345
1290
node_revision_t *noderev;
1347
/* Go get a fresh node-revision for FILE. */
1292
/* Go get a fresh node-revision for NODE. */
1348
1293
SVN_ERR(get_node_revision(&noderev, node, pool));
1350
1295
*path = noderev->copyfrom_path;
1352
1297
return SVN_NO_ERROR;
1301
svn_fs_fs__dag_update_ancestry(dag_node_t *target,
1305
node_revision_t *source_noderev, *target_noderev;
1307
if (! svn_fs_fs__dag_check_mutable(target))
1308
return svn_error_createf
1309
(SVN_ERR_FS_NOT_MUTABLE, NULL,
1310
_("Attempted to update ancestry of non-mutable node"));
1312
SVN_ERR(get_node_revision(&source_noderev, source, pool));
1313
SVN_ERR(get_node_revision(&target_noderev, target, pool));
1315
target_noderev->predecessor_id = source->id;
1316
target_noderev->predecessor_count = source_noderev->predecessor_count;
1317
if (target_noderev->predecessor_count != -1)
1318
target_noderev->predecessor_count++;
1320
return svn_fs_fs__put_node_revision(target->fs, target->id, target_noderev,