1251881Speter/* nodes-table.c : working with the `nodes' 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 <string.h> 24251881Speter#include <assert.h> 25251881Speter 26251881Speter#include "bdb_compat.h" 27251881Speter 28251881Speter#include "svn_fs.h" 29251881Speter#include "private/svn_skel.h" 30251881Speter 31251881Speter#include "../fs.h" 32251881Speter#include "../err.h" 33251881Speter#include "dbt.h" 34251881Speter#include "../util/fs_skels.h" 35251881Speter#include "../trail.h" 36251881Speter#include "../key-gen.h" 37251881Speter#include "../id.h" 38251881Speter#include "../../libsvn_fs/fs-loader.h" 39251881Speter#include "bdb-err.h" 40251881Speter#include "nodes-table.h" 41251881Speter 42251881Speter#include "svn_private_config.h" 43251881Speter 44251881Speter 45251881Speter 46251881Speter/* Opening/creating the `nodes' table. */ 47251881Speter 48251881Speter 49251881Speterint 50251881Spetersvn_fs_bdb__open_nodes_table(DB **nodes_p, 51251881Speter DB_ENV *env, 52251881Speter svn_boolean_t create) 53251881Speter{ 54251881Speter const u_int32_t open_flags = (create ? (DB_CREATE | DB_EXCL) : 0); 55251881Speter DB *nodes; 56251881Speter 57251881Speter BDB_ERR(svn_fs_bdb__check_version()); 58251881Speter BDB_ERR(db_create(&nodes, env, 0)); 59251881Speter BDB_ERR((nodes->open)(SVN_BDB_OPEN_PARAMS(nodes, NULL), 60251881Speter "nodes", 0, DB_BTREE, 61251881Speter open_flags, 0666)); 62251881Speter 63251881Speter /* Create the `next-key' table entry (use '1' because '0' is 64251881Speter reserved for the root directory to use). */ 65251881Speter if (create) 66251881Speter { 67251881Speter DBT key, value; 68251881Speter 69251881Speter BDB_ERR(nodes->put(nodes, 0, 70251881Speter svn_fs_base__str_to_dbt(&key, NEXT_KEY_KEY), 71251881Speter svn_fs_base__str_to_dbt(&value, "1"), 0)); 72251881Speter } 73251881Speter 74251881Speter *nodes_p = nodes; 75251881Speter return 0; 76251881Speter} 77251881Speter 78251881Speter 79251881Speter 80251881Speter/* Choosing node revision ID's. */ 81251881Speter 82251881Spetersvn_error_t * 83251881Spetersvn_fs_bdb__new_node_id(svn_fs_id_t **id_p, 84251881Speter svn_fs_t *fs, 85251881Speter const char *copy_id, 86251881Speter const char *txn_id, 87251881Speter trail_t *trail, 88251881Speter apr_pool_t *pool) 89251881Speter{ 90251881Speter base_fs_data_t *bfd = fs->fsap_data; 91251881Speter DBT query, result; 92251881Speter apr_size_t len; 93251881Speter char next_key[MAX_KEY_SIZE]; 94251881Speter int db_err; 95251881Speter const char *next_node_id; 96251881Speter 97251881Speter SVN_ERR_ASSERT(txn_id); 98251881Speter 99251881Speter /* Get the current value associated with the `next-key' key in the table. */ 100251881Speter svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY); 101251881Speter svn_fs_base__trail_debug(trail, "nodes", "get"); 102251881Speter SVN_ERR(BDB_WRAP(fs, N_("allocating new node ID (getting 'next-key')"), 103251881Speter bfd->nodes->get(bfd->nodes, trail->db_txn, 104251881Speter &query, 105251881Speter svn_fs_base__result_dbt(&result), 106251881Speter 0))); 107251881Speter svn_fs_base__track_dbt(&result, pool); 108251881Speter 109251881Speter /* Squirrel away our next node id value. */ 110251881Speter next_node_id = apr_pstrmemdup(pool, result.data, result.size); 111251881Speter 112251881Speter /* Bump to future key. */ 113251881Speter len = result.size; 114251881Speter svn_fs_base__next_key(result.data, &len, next_key); 115251881Speter svn_fs_base__trail_debug(trail, "nodes", "put"); 116251881Speter db_err = bfd->nodes->put(bfd->nodes, trail->db_txn, 117251881Speter svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY), 118251881Speter svn_fs_base__str_to_dbt(&result, next_key), 119251881Speter 0); 120251881Speter SVN_ERR(BDB_WRAP(fs, N_("bumping next node ID key"), db_err)); 121251881Speter 122251881Speter /* Create and return the new node id. */ 123251881Speter *id_p = svn_fs_base__id_create(next_node_id, copy_id, txn_id, pool); 124251881Speter return SVN_NO_ERROR; 125251881Speter} 126251881Speter 127251881Speter 128251881Spetersvn_error_t * 129251881Spetersvn_fs_bdb__new_successor_id(svn_fs_id_t **successor_p, 130251881Speter svn_fs_t *fs, 131251881Speter const svn_fs_id_t *id, 132251881Speter const char *copy_id, 133251881Speter const char *txn_id, 134251881Speter trail_t *trail, 135251881Speter apr_pool_t *pool) 136251881Speter{ 137251881Speter svn_fs_id_t *new_id; 138251881Speter svn_error_t *err; 139251881Speter 140251881Speter SVN_ERR_ASSERT(txn_id); 141251881Speter 142251881Speter /* Create and return the new successor ID. */ 143251881Speter new_id = svn_fs_base__id_create(svn_fs_base__id_node_id(id), 144251881Speter copy_id ? copy_id 145251881Speter : svn_fs_base__id_copy_id(id), 146251881Speter txn_id, pool); 147251881Speter 148251881Speter /* Now, make sure this NEW_ID doesn't already exist in FS. */ 149251881Speter err = svn_fs_bdb__get_node_revision(NULL, fs, new_id, trail, trail->pool); 150251881Speter if ((! err) || (err->apr_err != SVN_ERR_FS_ID_NOT_FOUND)) 151251881Speter { 152251881Speter svn_string_t *id_str = svn_fs_base__id_unparse(id, pool); 153251881Speter svn_string_t *new_id_str = svn_fs_base__id_unparse(new_id, pool); 154251881Speter return svn_error_createf 155251881Speter (SVN_ERR_FS_ALREADY_EXISTS, err, 156251881Speter _("Successor id '%s' (for '%s') already exists in filesystem '%s'"), 157251881Speter new_id_str->data, id_str->data, fs->path); 158251881Speter } 159251881Speter 160251881Speter /* err is SVN_ERR_FS_ID_NOT_FOUND, meaning the ID is available. But 161251881Speter we don't want this error. */ 162251881Speter svn_error_clear(err); 163251881Speter 164251881Speter /* Return the new node revision ID. */ 165251881Speter *successor_p = new_id; 166251881Speter return SVN_NO_ERROR; 167251881Speter} 168251881Speter 169251881Speter 170251881Speter 171251881Speter/* Removing node revisions. */ 172251881Spetersvn_error_t * 173251881Spetersvn_fs_bdb__delete_nodes_entry(svn_fs_t *fs, 174251881Speter const svn_fs_id_t *id, 175251881Speter trail_t *trail, 176251881Speter apr_pool_t *pool) 177251881Speter{ 178251881Speter base_fs_data_t *bfd = fs->fsap_data; 179251881Speter DBT key; 180251881Speter 181251881Speter svn_fs_base__trail_debug(trail, "nodes", "del"); 182251881Speter return BDB_WRAP(fs, N_("deleting entry from 'nodes' table"), 183251881Speter bfd->nodes->del(bfd->nodes, 184251881Speter trail->db_txn, 185251881Speter svn_fs_base__id_to_dbt(&key, id, pool), 186251881Speter 0)); 187251881Speter} 188251881Speter 189251881Speter 190251881Speter 191251881Speter 192251881Speter/* Storing and retrieving NODE-REVISIONs. */ 193251881Speter 194251881Speter 195251881Spetersvn_error_t * 196251881Spetersvn_fs_bdb__get_node_revision(node_revision_t **noderev_p, 197251881Speter svn_fs_t *fs, 198251881Speter const svn_fs_id_t *id, 199251881Speter trail_t *trail, 200251881Speter apr_pool_t *pool) 201251881Speter{ 202251881Speter base_fs_data_t *bfd = fs->fsap_data; 203251881Speter node_revision_t *noderev; 204251881Speter svn_skel_t *skel; 205251881Speter int db_err; 206251881Speter DBT key, value; 207251881Speter 208251881Speter svn_fs_base__trail_debug(trail, "nodes", "get"); 209251881Speter db_err = bfd->nodes->get(bfd->nodes, trail->db_txn, 210251881Speter svn_fs_base__id_to_dbt(&key, id, pool), 211251881Speter svn_fs_base__result_dbt(&value), 212251881Speter 0); 213251881Speter svn_fs_base__track_dbt(&value, pool); 214251881Speter 215251881Speter /* If there's no such node, return an appropriately specific error. */ 216251881Speter if (db_err == DB_NOTFOUND) 217251881Speter return svn_fs_base__err_dangling_id(fs, id); 218251881Speter 219251881Speter /* Handle any other error conditions. */ 220251881Speter SVN_ERR(BDB_WRAP(fs, N_("reading node revision"), db_err)); 221251881Speter 222251881Speter /* If our caller doesn't really care about the return value here, 223251881Speter just return successfully. */ 224251881Speter if (! noderev_p) 225251881Speter return SVN_NO_ERROR; 226251881Speter 227251881Speter /* Parse and the NODE-REVISION skel. */ 228251881Speter skel = svn_skel__parse(value.data, value.size, pool); 229251881Speter 230251881Speter /* Convert to a native FS type. */ 231251881Speter SVN_ERR(svn_fs_base__parse_node_revision_skel(&noderev, skel, pool)); 232251881Speter *noderev_p = noderev; 233251881Speter return SVN_NO_ERROR; 234251881Speter} 235251881Speter 236251881Speter 237251881Spetersvn_error_t * 238251881Spetersvn_fs_bdb__put_node_revision(svn_fs_t *fs, 239251881Speter const svn_fs_id_t *id, 240251881Speter node_revision_t *noderev, 241251881Speter trail_t *trail, 242251881Speter apr_pool_t *pool) 243251881Speter{ 244251881Speter base_fs_data_t *bfd = fs->fsap_data; 245251881Speter DB_TXN *db_txn = trail->db_txn; 246251881Speter DBT key, value; 247251881Speter svn_skel_t *skel; 248251881Speter 249251881Speter /* Convert from native type into skel */ 250251881Speter SVN_ERR(svn_fs_base__unparse_node_revision_skel(&skel, noderev, 251251881Speter bfd->format, pool)); 252251881Speter svn_fs_base__trail_debug(trail, "nodes", "put"); 253251881Speter return BDB_WRAP(fs, N_("storing node revision"), 254251881Speter bfd->nodes->put(bfd->nodes, db_txn, 255251881Speter svn_fs_base__id_to_dbt(&key, id, pool), 256251881Speter svn_fs_base__skel_to_dbt(&value, skel, 257251881Speter pool), 258251881Speter 0)); 259251881Speter} 260