11 const std::string SqliteHistory::kPreviousRevisionKey =
"previous_revision";
15 const bool read_write =
false;
16 return Open(file_name, read_write);
20 SqliteHistory* SqliteHistory::OpenWritable(
const std::string &file_name) {
21 const bool read_write =
true;
22 return Open(file_name, read_write);
27 const bool read_write) {
29 if (NULL == history || !history->
OpenDatabase(file_name, read_write)) {
35 "opened history database '%s' for repository '%s' %s",
36 file_name.c_str(), history->
fqrn().c_str(),
37 ((history->
IsWritable()) ?
"(writable)" :
""));
44 const std::string &fqrn) {
46 if (NULL == history || !history->
CreateDatabase(file_name, fqrn)) {
53 file_name.c_str(), fqrn.c_str());
58 bool SqliteHistory::OpenDatabase(
59 const std::string &file_name,
62 assert(!database_.IsValid());
64 ? HistoryDatabase::kOpenReadWrite
65 : HistoryDatabase::kOpenReadOnly;
67 if (!database_.IsValid()) {
71 if (!database_->HasProperty(HistoryDatabase::kFqrnKey)) {
74 HistoryDatabase::kFqrnKey.c_str());
78 set_fqrn(database_->GetProperty<std::string>(HistoryDatabase::kFqrnKey));
84 bool SqliteHistory::CreateDatabase(
const std::string &file_name,
85 const std::string &repo_name) {
86 assert(!database_.IsValid());
90 if (!database_.IsValid() || !database_->InsertInitialValues(repo_name)) {
92 "failed to initialize empty database '%s', for repository '%s'",
93 file_name.c_str(), repo_name.c_str());
102 void SqliteHistory::PrepareQueries() {
103 assert(database_.IsValid());
105 find_tag_ =
new SqlFindTag (database_.weak_ref());
108 list_tags_ =
new SqlListTags (database_.weak_ref());
113 if (database_->ContainsRecycleBin()) {
128 bool SqliteHistory::BeginTransaction()
const {
129 return database_->BeginTransaction();
133 bool SqliteHistory::CommitTransaction()
const {
134 return database_->CommitTransaction();
138 bool SqliteHistory::SetPreviousRevision(
const shash::Any &history_hash) {
139 assert(database_.IsValid());
141 return database_->SetProperty(kPreviousRevisionKey, history_hash.
ToString());
146 assert(database_.IsValid());
147 const std::string hash_str =
148 database_->GetProperty<std::string>(kPreviousRevisionKey);
153 bool SqliteHistory::IsWritable()
const {
154 assert(database_.IsValid());
155 return database_->read_write();
158 unsigned SqliteHistory::GetNumberOfTags()
const {
159 assert(database_.IsValid());
160 assert(count_tags_.IsValid());
161 bool retval = count_tags_->FetchRow();
163 const unsigned count = count_tags_->RetrieveCount();
164 retval = count_tags_->Reset();
171 assert(database_.IsValid());
172 assert(insert_tag_.IsValid());
174 return insert_tag_->BindTag(tag) &&
175 insert_tag_->Execute() &&
176 insert_tag_->Reset();
180 bool SqliteHistory::Remove(
const std::string &name) {
181 assert(database_.IsValid());
182 assert(remove_tag_.IsValid());
185 if (!GetByName(name, &condemned_tag)) {
189 return remove_tag_->BindName(name) &&
190 remove_tag_->Execute() &&
191 remove_tag_->Reset();
195 bool SqliteHistory::Exists(
const std::string &name)
const {
197 return GetByName(name, &existing_tag);
201 bool SqliteHistory::GetByName(
const std::string &name,
Tag *tag)
const {
202 assert(database_.IsValid());
203 assert(find_tag_.IsValid());
206 if (!find_tag_->BindName(name) || !find_tag_->FetchRow()) {
211 *tag = find_tag_->RetrieveTag();
212 return find_tag_->Reset();
216 bool SqliteHistory::GetByDate(
const time_t timestamp,
Tag *tag)
const {
217 assert(database_.IsValid());
218 assert(find_tag_by_date_.IsValid());
221 if (!find_tag_by_date_->BindTimestamp(timestamp) ||
222 !find_tag_by_date_->FetchRow())
224 find_tag_by_date_->Reset();
228 *tag = find_tag_by_date_->RetrieveTag();
229 return find_tag_by_date_->Reset();
234 assert(list_tags_.IsValid());
235 return RunListing(tags, list_tags_.weak_ref());
239 template <
class SqlListingT>
240 bool SqliteHistory::RunListing(std::vector<Tag> *list, SqlListingT *sql)
const {
241 assert(database_.IsValid());
244 while (sql->FetchRow()) {
245 list->push_back(sql->RetrieveTag());
252 bool SqliteHistory::GetBranchHead(
const string &branch_name,
Tag *tag)
const {
253 assert(database_.IsValid());
254 assert(find_branch_head_.IsValid());
257 if (!find_branch_head_->BindBranchName(branch_name) ||
258 !find_branch_head_->FetchRow())
260 find_branch_head_->Reset();
264 *tag = find_branch_head_->RetrieveTag();
265 return find_branch_head_->Reset();
269 bool SqliteHistory::ExistsBranch(
const string &branch_name)
const {
270 vector<Branch> branches;
271 if (!ListBranches(&branches))
273 for (
unsigned i = 0; i < branches.size(); ++i) {
274 if (branches[i].branch == branch_name)
281 bool SqliteHistory::InsertBranch(
const Branch &branch) {
282 assert(database_.IsValid());
283 assert(insert_branch_.IsValid());
285 return insert_branch_->BindBranch(branch) &&
286 insert_branch_->Execute() &&
287 insert_branch_->Reset();
291 bool SqliteHistory::PruneBranches() {
295 sqlite::Sql sql_fix_parent_pointers(database_->sqlite_db(),
296 "INSERT OR REPLACE INTO branches (branch, parent, initial_revision) "
297 "SELECT branches.branch, abandoned_parent, branches.initial_revision "
299 " INNER JOIN (SELECT DISTINCT branches.branch AS abandoned_branch, "
300 " branches.parent AS abandoned_parent FROM branches "
301 " LEFT OUTER JOIN tags ON (branches.branch=tags.branch)"
302 " WHERE tags.branch IS NULL) "
303 " ON (branches.parent=abandoned_branch);");
305 sqlite::Sql sql_remaining_rows(database_->sqlite_db(),
306 "SELECT count(*) FROM branches "
308 " (SELECT DISTINCT branches.branch AS abandoned_branch FROM branches "
309 " LEFT OUTER JOIN tags ON (branches.branch=tags.branch) "
310 " WHERE tags.branch IS NULL) "
311 "ON (branches.parent=abandoned_branch);");
315 retval = sql_remaining_rows.
FetchRow();
318 int64_t count = sql_remaining_rows.RetrieveInt64(0);
322 retval = sql_remaining_rows.Reset();
325 retval = sql_fix_parent_pointers.Execute();
328 retval = sql_fix_parent_pointers.Reset();
332 sqlite::Sql sql_remove_branches(database_->sqlite_db(),
333 "DELETE FROM branches "
334 "WHERE branch NOT IN (SELECT DISTINCT branch FROM tags);");
335 retval = sql_remove_branches.
Execute();
340 bool SqliteHistory::ListBranches(vector<Branch> *branches)
const {
341 while (list_branches_->FetchRow()) {
342 branches->push_back(list_branches_->RetrieveBranch());
345 return list_branches_->Reset();
349 bool SqliteHistory::ListRecycleBin(std::vector<shash::Any> *hashes)
const {
350 assert(database_.IsValid());
352 if (!database_->ContainsRecycleBin()) {
358 while (recycle_list_->FetchRow()) {
359 hashes->push_back(recycle_list_->RetrieveHash());
362 return recycle_list_->Reset();
366 bool SqliteHistory::EmptyRecycleBin() {
367 assert(database_.IsValid());
369 assert(recycle_empty_.IsValid());
370 return recycle_empty_->Execute() &&
371 recycle_empty_->Reset();
376 assert(database_.IsValid());
378 assert(rollback_tag_.IsValid());
381 bool success =
false;
384 const bool need_to_commit = BeginTransaction();
387 success = GetByName(updated_target_tag.
name, &old_target_tag);
390 updated_target_tag.
name.c_str());
399 success = rollback_tag_->BindTargetTag(old_target_tag) &&
400 rollback_tag_->Execute() &&
401 rollback_tag_->Reset();
402 if (!success || Exists(old_target_tag.name)) {
404 "until '%s' - '%" PRIu64
"'",
405 old_target_tag.name.c_str(),
406 old_target_tag.revision);
412 success = Insert(updated_target_tag);
415 updated_target_tag.
name.c_str());
419 if (need_to_commit) {
420 success = CommitTransaction();
428 bool SqliteHistory::ListTagsAffectedByRollback(
429 const std::string &target_tag_name,
430 std::vector<Tag> *tags)
const {
433 if (!GetByName(target_tag_name, &target_tag)) {
435 target_tag_name.c_str());
440 if (!list_rollback_tags_->BindTargetTag(target_tag)) {
442 "failed to prepare rollback listing query");
447 return RunListing(tags, list_rollback_tags_.weak_ref());
451 bool SqliteHistory::GetHashes(std::vector<shash::Any> *hashes)
const {
452 assert(database_.IsValid());
455 while (get_hashes_->FetchRow()) {
456 hashes->push_back(get_hashes_->RetrieveHash());
459 return get_hashes_->Reset();
463 void SqliteHistory::TakeDatabaseFileOwnership() {
464 assert(database_.IsValid());
465 database_->TakeFileOwnership();
469 void SqliteHistory::DropDatabaseFileOwnership() {
470 assert(database_.IsValid());
471 database_->DropFileOwnership();
static Publisher * Create(const SettingsPublisher &settings)
std::string ToString(const bool with_suffix=false) const
const history::History * history() const
assert((mem||(size==0))&&"Out Of Memory")
const std::string & fqrn() const
bool OpenDatabase(const std::string &file_name, const bool read_write)
bool CreateDatabase(const std::string &file_name, const std::string &fqrn)
const char kSuffixHistory
Any MkFromHexPtr(const HexPtr hex, const char suffix)
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)