1/* copies-table.c : operations on the `copies' table
2 *
3 * ====================================================================
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
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
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
19 *    under the License.
20 * ====================================================================
21 */
22
23#include <string.h>
24
25#include "bdb_compat.h"
26
27#include "private/svn_skel.h"
28
29#include "../fs.h"
30#include "../err.h"
31#include "../key-gen.h"
32#include "dbt.h"
33#include "../util/fs_skels.h"
34#include "../trail.h"
35#include "../../libsvn_fs/fs-loader.h"
36#include "bdb-err.h"
37#include "copies-table.h"
38#include "rev-table.h"
39
40#include "svn_private_config.h"
41
42
43int
44svn_fs_bdb__open_copies_table(DB **copies_p,
45                              DB_ENV *env,
46                              svn_boolean_t create)
47{
48  const u_int32_t open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
49  DB *copies;
50
51  BDB_ERR(svn_fs_bdb__check_version());
52  BDB_ERR(db_create(&copies, env, 0));
53  BDB_ERR((copies->open)(SVN_BDB_OPEN_PARAMS(copies, NULL),
54                         "copies", 0, DB_BTREE,
55                         open_flags, 0666));
56
57  /* Create the initial `next-key' table entry.  */
58  if (create)
59  {
60    DBT key, value;
61    BDB_ERR(copies->put(copies, 0,
62                        svn_fs_base__str_to_dbt(&key, NEXT_KEY_KEY),
63                        svn_fs_base__str_to_dbt(&value, "0"), 0));
64  }
65
66  *copies_p = copies;
67  return 0;
68}
69
70
71/* Store COPY as a copy named COPY_ID in FS as part of TRAIL.  */
72/* ### only has one caller; might not need to be abstracted */
73static svn_error_t *
74put_copy(svn_fs_t *fs,
75         const copy_t *copy,
76         const char *copy_id,
77         trail_t *trail,
78         apr_pool_t *pool)
79{
80  base_fs_data_t *bfd = fs->fsap_data;
81  svn_skel_t *copy_skel;
82  DBT key, value;
83
84  /* Convert native type to skel. */
85  SVN_ERR(svn_fs_base__unparse_copy_skel(&copy_skel, copy, pool));
86
87  /* Only in the context of this function do we know that the DB call
88     will not attempt to modify COPY_ID, so the cast belongs here.  */
89  svn_fs_base__str_to_dbt(&key, copy_id);
90  svn_fs_base__skel_to_dbt(&value, copy_skel, pool);
91  svn_fs_base__trail_debug(trail, "copies", "put");
92  return BDB_WRAP(fs, N_("storing copy record"),
93                  bfd->copies->put(bfd->copies, trail->db_txn,
94                                   &key, &value, 0));
95}
96
97
98svn_error_t *
99svn_fs_bdb__reserve_copy_id(const char **id_p,
100                            svn_fs_t *fs,
101                            trail_t *trail,
102                            apr_pool_t *pool)
103{
104  base_fs_data_t *bfd = fs->fsap_data;
105  DBT query, result;
106  apr_size_t len;
107  char next_key[MAX_KEY_SIZE];
108  int db_err;
109
110  svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY);
111
112  /* Get the current value associated with the `next-key' key in the
113     copies table.  */
114  svn_fs_base__trail_debug(trail, "copies", "get");
115  SVN_ERR(BDB_WRAP(fs, N_("allocating new copy ID (getting 'next-key')"),
116                   bfd->copies->get(bfd->copies, trail->db_txn, &query,
117                                    svn_fs_base__result_dbt(&result),
118                                    0)));
119  svn_fs_base__track_dbt(&result, pool);
120
121  /* Set our return value. */
122  *id_p = apr_pstrmemdup(pool, result.data, result.size);
123
124  /* Bump to future key. */
125  len = result.size;
126  svn_fs_base__next_key(result.data, &len, next_key);
127  svn_fs_base__trail_debug(trail, "copies", "put");
128  db_err = bfd->copies->put(bfd->copies, trail->db_txn,
129                            svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY),
130                            svn_fs_base__str_to_dbt(&result, next_key),
131                            0);
132
133  return BDB_WRAP(fs, N_("bumping next copy key"), db_err);
134}
135
136
137svn_error_t *
138svn_fs_bdb__create_copy(svn_fs_t *fs,
139                        const char *copy_id,
140                        const char *src_path,
141                        const char *src_txn_id,
142                        const svn_fs_id_t *dst_noderev_id,
143                        copy_kind_t kind,
144                        trail_t *trail,
145                        apr_pool_t *pool)
146{
147  copy_t copy;
148  copy.kind = kind;
149  copy.src_path = src_path;
150  copy.src_txn_id = src_txn_id;
151  copy.dst_noderev_id = dst_noderev_id;
152  return put_copy(fs, &copy, copy_id, trail, pool);
153}
154
155
156svn_error_t *
157svn_fs_bdb__delete_copy(svn_fs_t *fs,
158                        const char *copy_id,
159                        trail_t *trail,
160                        apr_pool_t *pool)
161{
162  base_fs_data_t *bfd = fs->fsap_data;
163  DBT key;
164  int db_err;
165
166  svn_fs_base__str_to_dbt(&key, copy_id);
167  svn_fs_base__trail_debug(trail, "copies", "del");
168  db_err = bfd->copies->del(bfd->copies, trail->db_txn, &key, 0);
169  if (db_err == DB_NOTFOUND)
170    return svn_fs_base__err_no_such_copy(fs, copy_id);
171  return BDB_WRAP(fs, N_("deleting entry from 'copies' table"), db_err);
172}
173
174
175svn_error_t *
176svn_fs_bdb__get_copy(copy_t **copy_p,
177                     svn_fs_t *fs,
178                     const char *copy_id,
179                     trail_t *trail,
180                     apr_pool_t *pool)
181{
182  base_fs_data_t *bfd = fs->fsap_data;
183  DBT key, value;
184  int db_err;
185  svn_skel_t *skel;
186  copy_t *copy;
187
188  /* Only in the context of this function do we know that the DB call
189     will not attempt to modify copy_id, so the cast belongs here.  */
190  svn_fs_base__trail_debug(trail, "copies", "get");
191  db_err = bfd->copies->get(bfd->copies, trail->db_txn,
192                            svn_fs_base__str_to_dbt(&key, copy_id),
193                            svn_fs_base__result_dbt(&value),
194                            0);
195  svn_fs_base__track_dbt(&value, pool);
196
197  if (db_err == DB_NOTFOUND)
198    return svn_fs_base__err_no_such_copy(fs, copy_id);
199  SVN_ERR(BDB_WRAP(fs, N_("reading copy"), db_err));
200
201  /* Unparse COPY skel */
202  skel = svn_skel__parse(value.data, value.size, pool);
203  if (! skel)
204    return svn_fs_base__err_corrupt_copy(fs, copy_id);
205
206  /* Convert skel to native type. */
207  SVN_ERR(svn_fs_base__parse_copy_skel(&copy, skel, pool));
208  *copy_p = copy;
209  return SVN_NO_ERROR;
210}
211