1251881Speter/* checksum-reps-table.c : operations on the `checksum-reps' table
2251881Speter *
3251881Speter * ====================================================================
4251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
5251881Speter *    or more contributor license agreements.  See the NOTICE file
6251881Speter *    distributed with this work for additional information
7251881Speter *    regarding copyright ownership.  The ASF licenses this file
8251881Speter *    to you under the Apache License, Version 2.0 (the
9251881Speter *    "License"); you may not use this file except in compliance
10251881Speter *    with the License.  You may obtain a copy of the License at
11251881Speter *
12251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
13251881Speter *
14251881Speter *    Unless required by applicable law or agreed to in writing,
15251881Speter *    software distributed under the License is distributed on an
16251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17251881Speter *    KIND, either express or implied.  See the License for the
18251881Speter *    specific language governing permissions and limitations
19251881Speter *    under the License.
20251881Speter * ====================================================================
21251881Speter */
22251881Speter
23251881Speter#include <apr_strings.h>
24251881Speter
25251881Speter#include "bdb_compat.h"
26251881Speter#include "../fs.h"
27251881Speter#include "../err.h"
28251881Speter#include "../key-gen.h"
29251881Speter#include "dbt.h"
30251881Speter#include "../trail.h"
31251881Speter#include "bdb-err.h"
32251881Speter#include "../../libsvn_fs/fs-loader.h"
33251881Speter#include "checksum-reps-table.h"
34251881Speter
35251881Speter#include "svn_private_config.h"
36251881Speter
37251881Speter
38251881Speterint svn_fs_bdb__open_checksum_reps_table(DB **checksum_reps_p,
39251881Speter                                         DB_ENV *env,
40251881Speter                                         svn_boolean_t create)
41251881Speter{
42251881Speter  const u_int32_t open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
43251881Speter  DB *checksum_reps;
44251881Speter  int error;
45251881Speter
46251881Speter  BDB_ERR(svn_fs_bdb__check_version());
47251881Speter  BDB_ERR(db_create(&checksum_reps, env, 0));
48251881Speter  error = (checksum_reps->open)(SVN_BDB_OPEN_PARAMS(checksum_reps, NULL),
49251881Speter                                "checksum-reps", 0, DB_BTREE,
50251881Speter                                open_flags, 0666);
51251881Speter
52251881Speter  /* Create the checksum-reps table if it doesn't exist. */
53251881Speter  if (error == ENOENT && (! create))
54251881Speter    {
55251881Speter      BDB_ERR(checksum_reps->close(checksum_reps, 0));
56251881Speter      return svn_fs_bdb__open_checksum_reps_table(checksum_reps_p, env, TRUE);
57251881Speter    }
58251881Speter
59251881Speter  /* Create the initial `next-key' table entry.  */
60251881Speter  if (create)
61251881Speter    {
62251881Speter      DBT key, value;
63251881Speter      BDB_ERR(checksum_reps->put(checksum_reps, 0,
64251881Speter                                 svn_fs_base__str_to_dbt(&key, NEXT_KEY_KEY),
65251881Speter                                 svn_fs_base__str_to_dbt(&value, "0"), 0));
66251881Speter    }
67251881Speter
68251881Speter  BDB_ERR(error);
69251881Speter
70251881Speter  *checksum_reps_p = checksum_reps;
71251881Speter  return 0;
72251881Speter}
73251881Speter
74251881Spetersvn_error_t *svn_fs_bdb__get_checksum_rep(const char **rep_key,
75251881Speter                                          svn_fs_t *fs,
76251881Speter                                          svn_checksum_t *checksum,
77251881Speter                                          trail_t *trail,
78251881Speter                                          apr_pool_t *pool)
79251881Speter{
80251881Speter  base_fs_data_t *bfd = fs->fsap_data;
81251881Speter  DBT key, value;
82251881Speter  int db_err;
83251881Speter
84251881Speter  /* We only allow SHA1 checksums in this table. */
85251881Speter  if (checksum->kind != svn_checksum_sha1)
86251881Speter    return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL,
87251881Speter                            _("Only SHA1 checksums can be used as keys in the "
88251881Speter                              "checksum-reps table.\n"));
89251881Speter
90251881Speter  svn_fs_base__trail_debug(trail, "checksum-reps", "get");
91251881Speter  db_err = bfd->checksum_reps->get(bfd->checksum_reps, trail->db_txn,
92251881Speter                                   svn_fs_base__checksum_to_dbt(&key, checksum),
93251881Speter                                   svn_fs_base__result_dbt(&value), 0);
94251881Speter  svn_fs_base__track_dbt(&value, pool);
95251881Speter
96251881Speter  if (db_err == DB_NOTFOUND)
97251881Speter    return svn_fs_base__err_no_such_checksum_rep(fs, checksum);
98251881Speter
99251881Speter  *rep_key = apr_pstrmemdup(pool, value.data, value.size);
100251881Speter  return SVN_NO_ERROR;
101251881Speter}
102251881Speter
103251881Spetersvn_error_t *svn_fs_bdb__set_checksum_rep(svn_fs_t *fs,
104251881Speter                                          svn_checksum_t *checksum,
105251881Speter                                          const char *rep_key,
106251881Speter                                          trail_t *trail,
107251881Speter                                          apr_pool_t *pool)
108251881Speter{
109251881Speter  base_fs_data_t *bfd = fs->fsap_data;
110251881Speter  DBT key, value;
111251881Speter  int db_err;
112251881Speter
113251881Speter  /* We only allow SHA1 checksums in this table. */
114251881Speter  if (checksum->kind != svn_checksum_sha1)
115251881Speter    return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL,
116251881Speter                            _("Only SHA1 checksums can be used as keys in the "
117251881Speter                              "checksum-reps table.\n"));
118251881Speter
119251881Speter  /* Create a key from our CHECKSUM. */
120251881Speter  svn_fs_base__checksum_to_dbt(&key, checksum);
121251881Speter
122251881Speter  /* Check to see if we already have a mapping for CHECKSUM.  If so,
123251881Speter     and the value is the same one we were about to write, that's
124251881Speter     cool -- just do nothing.  If, however, the value is *different*,
125251881Speter     that's a red flag!  */
126251881Speter  svn_fs_base__trail_debug(trail, "checksum-reps", "get");
127251881Speter  db_err = bfd->checksum_reps->get(bfd->checksum_reps, trail->db_txn,
128251881Speter                                   &key, svn_fs_base__result_dbt(&value), 0);
129251881Speter  svn_fs_base__track_dbt(&value, pool);
130251881Speter  if (db_err != DB_NOTFOUND)
131251881Speter    {
132251881Speter      const char *sum_str = svn_checksum_to_cstring_display(checksum, pool);
133251881Speter      return svn_error_createf
134251881Speter        (SVN_ERR_FS_ALREADY_EXISTS, NULL,
135251881Speter         _("Representation key for checksum '%s' exists in filesystem '%s'."),
136251881Speter         sum_str, fs->path);
137251881Speter    }
138251881Speter
139251881Speter  /* Create a value from our REP_KEY, and add this record to the table. */
140251881Speter  svn_fs_base__str_to_dbt(&value, rep_key);
141251881Speter  svn_fs_base__trail_debug(trail, "checksum-reps", "put");
142251881Speter  SVN_ERR(BDB_WRAP(fs, N_("storing checksum-reps record"),
143251881Speter                   bfd->checksum_reps->put(bfd->checksum_reps, trail->db_txn,
144251881Speter                                           &key, &value, 0)));
145251881Speter  return SVN_NO_ERROR;
146251881Speter}
147251881Speter
148251881Spetersvn_error_t *svn_fs_bdb__delete_checksum_rep(svn_fs_t *fs,
149251881Speter                                             svn_checksum_t *checksum,
150251881Speter                                             trail_t *trail,
151251881Speter                                             apr_pool_t *pool)
152251881Speter{
153251881Speter  base_fs_data_t *bfd = fs->fsap_data;
154251881Speter  DBT key;
155251881Speter
156251881Speter  /* We only allow SHA1 checksums in this table. */
157251881Speter  if (checksum->kind != svn_checksum_sha1)
158251881Speter    return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL,
159251881Speter                            _("Only SHA1 checksums can be used as keys in the "
160251881Speter                              "checksum-reps table.\n"));
161251881Speter
162251881Speter  svn_fs_base__checksum_to_dbt(&key, checksum);
163251881Speter  svn_fs_base__trail_debug(trail, "checksum-reps", "del");
164251881Speter  SVN_ERR(BDB_WRAP(fs, N_("deleting entry from 'checksum-reps' table"),
165251881Speter                   bfd->checksum_reps->del(bfd->checksum_reps,
166251881Speter                                           trail->db_txn, &key, 0)));
167251881Speter  return SVN_NO_ERROR;
168251881Speter}
169251881Speter
170251881Spetersvn_error_t *svn_fs_bdb__reserve_rep_reuse_id(const char **id_p,
171251881Speter                                              svn_fs_t *fs,
172251881Speter                                              trail_t *trail,
173251881Speter                                              apr_pool_t *pool)
174251881Speter{
175251881Speter  base_fs_data_t *bfd = fs->fsap_data;
176251881Speter  DBT query, result;
177251881Speter  apr_size_t len;
178251881Speter  char next_key[MAX_KEY_SIZE];
179251881Speter  int db_err;
180251881Speter
181251881Speter  svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY);
182251881Speter
183251881Speter  /* Get the current value associated with the `next-key' key in the
184251881Speter     `checksum-reps' table.  */
185251881Speter  svn_fs_base__trail_debug(trail, "checksum-reps", "get");
186251881Speter  SVN_ERR(BDB_WRAP(fs, N_("allocating new representation reuse ID "
187251881Speter                         "(getting 'next-key')"),
188251881Speter                   bfd->checksum_reps->get(bfd->checksum_reps, trail->db_txn,
189251881Speter                                           &query,
190251881Speter                                           svn_fs_base__result_dbt(&result),
191251881Speter                                           0)));
192251881Speter  svn_fs_base__track_dbt(&result, pool);
193251881Speter
194251881Speter  /* Set our return value. */
195251881Speter  *id_p = apr_pstrmemdup(pool, result.data, result.size);
196251881Speter
197251881Speter  /* Bump to future key. */
198251881Speter  len = result.size;
199251881Speter  svn_fs_base__next_key(result.data, &len, next_key);
200251881Speter  svn_fs_base__trail_debug(trail, "checksum_reps", "put");
201251881Speter  db_err = bfd->checksum_reps->put(bfd->checksum_reps, trail->db_txn,
202251881Speter                                   svn_fs_base__str_to_dbt(&query,
203251881Speter                                                           NEXT_KEY_KEY),
204251881Speter                                   svn_fs_base__str_to_dbt(&result, next_key),
205251881Speter                                   0);
206251881Speter
207251881Speter  return BDB_WRAP(fs, N_("bumping next representation reuse ID"), db_err);
208251881Speter}
209