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)) {
52 "created empty history database '%s' for"
54 file_name.c_str(), fqrn.c_str());
59 bool SqliteHistory::OpenDatabase(
const std::string &file_name,
60 const bool read_write) {
61 assert(!database_.IsValid());
63 ? HistoryDatabase::kOpenReadWrite
64 : HistoryDatabase::kOpenReadOnly;
66 if (!database_.IsValid()) {
70 if (!database_->HasProperty(HistoryDatabase::kFqrnKey)) {
72 "opened history database does not provide "
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 = database_->GetProperty<std::string>(
148 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) && insert_tag_->Execute()
175 && insert_tag_->Reset();
179 bool SqliteHistory::Remove(
const std::string &name) {
180 assert(database_.IsValid());
181 assert(remove_tag_.IsValid());
184 if (!GetByName(name, &condemned_tag)) {
188 return remove_tag_->BindName(name) && remove_tag_->Execute()
189 && remove_tag_->Reset();
193 bool SqliteHistory::Exists(
const std::string &name)
const {
195 return GetByName(name, &existing_tag);
199 bool SqliteHistory::GetByName(
const std::string &name,
Tag *tag)
const {
200 assert(database_.IsValid());
201 assert(find_tag_.IsValid());
204 if (!find_tag_->BindName(name) || !find_tag_->FetchRow()) {
209 *tag = find_tag_->RetrieveTag();
210 return find_tag_->Reset();
214 bool SqliteHistory::GetByDate(
const time_t timestamp,
Tag *tag)
const {
215 assert(database_.IsValid());
216 assert(find_tag_by_date_.IsValid());
219 if (!find_tag_by_date_->BindTimestamp(timestamp)
220 || !find_tag_by_date_->FetchRow()) {
221 find_tag_by_date_->Reset();
225 *tag = find_tag_by_date_->RetrieveTag();
226 return find_tag_by_date_->Reset();
231 assert(list_tags_.IsValid());
232 return RunListing(tags, list_tags_.weak_ref());
236 template<
class SqlListingT>
237 bool SqliteHistory::RunListing(std::vector<Tag> *list, SqlListingT *sql)
const {
238 assert(database_.IsValid());
241 while (sql->FetchRow()) {
242 list->push_back(sql->RetrieveTag());
249 bool SqliteHistory::GetBranchHead(
const string &branch_name,
Tag *tag)
const {
250 assert(database_.IsValid());
251 assert(find_branch_head_.IsValid());
254 if (!find_branch_head_->BindBranchName(branch_name)
255 || !find_branch_head_->FetchRow()) {
256 find_branch_head_->Reset();
260 *tag = find_branch_head_->RetrieveTag();
261 return find_branch_head_->Reset();
265 bool SqliteHistory::ExistsBranch(
const string &branch_name)
const {
266 vector<Branch> branches;
267 if (!ListBranches(&branches))
269 for (
unsigned i = 0; i < branches.size(); ++i) {
270 if (branches[i].branch == branch_name)
277 bool SqliteHistory::InsertBranch(
const Branch &branch) {
278 assert(database_.IsValid());
279 assert(insert_branch_.IsValid());
281 return insert_branch_->BindBranch(branch) && insert_branch_->Execute()
282 && insert_branch_->Reset();
286 bool SqliteHistory::PruneBranches() {
291 database_->sqlite_db(),
292 "INSERT OR REPLACE INTO branches (branch, parent, initial_revision) "
293 "SELECT branches.branch, abandoned_parent, branches.initial_revision "
295 " INNER JOIN (SELECT DISTINCT branches.branch AS abandoned_branch, "
296 " branches.parent AS abandoned_parent FROM branches "
297 " LEFT OUTER JOIN tags ON (branches.branch=tags.branch)"
298 " WHERE tags.branch IS NULL) "
299 " ON (branches.parent=abandoned_branch);");
302 database_->sqlite_db(),
303 "SELECT count(*) FROM branches "
305 " (SELECT DISTINCT branches.branch AS abandoned_branch FROM branches "
306 " LEFT OUTER JOIN tags ON (branches.branch=tags.branch) "
307 " WHERE tags.branch IS NULL) "
308 "ON (branches.parent=abandoned_branch);");
312 retval = sql_remaining_rows.
FetchRow();
315 int64_t count = sql_remaining_rows.RetrieveInt64(0);
319 retval = sql_remaining_rows.Reset();
322 retval = sql_fix_parent_pointers.Execute();
325 retval = sql_fix_parent_pointers.Reset();
330 database_->sqlite_db(),
331 "DELETE FROM branches "
332 "WHERE branch NOT IN (SELECT DISTINCT branch FROM tags);");
333 retval = sql_remove_branches.
Execute();
338 bool SqliteHistory::ListBranches(vector<Branch> *branches)
const {
339 while (list_branches_->FetchRow()) {
340 branches->push_back(list_branches_->RetrieveBranch());
343 return list_branches_->Reset();
347 bool SqliteHistory::ListRecycleBin(std::vector<shash::Any> *hashes)
const {
348 assert(database_.IsValid());
350 if (!database_->ContainsRecycleBin()) {
356 while (recycle_list_->FetchRow()) {
357 hashes->push_back(recycle_list_->RetrieveHash());
360 return recycle_list_->Reset();
364 bool SqliteHistory::EmptyRecycleBin() {
365 assert(database_.IsValid());
367 assert(recycle_empty_.IsValid());
368 return recycle_empty_->Execute() && recycle_empty_->Reset();
373 assert(database_.IsValid());
375 assert(rollback_tag_.IsValid());
378 bool success =
false;
381 const bool need_to_commit = BeginTransaction();
384 success = GetByName(updated_target_tag.
name, &old_target_tag);
387 updated_target_tag.
name.c_str());
396 success = rollback_tag_->BindTargetTag(old_target_tag)
397 && rollback_tag_->Execute() && rollback_tag_->Reset();
398 if (!success || Exists(old_target_tag.name)) {
400 "failed to remove intermediate tags "
401 "until '%s' - '%" PRIu64
"'",
402 old_target_tag.name.c_str(), old_target_tag.revision);
408 success = Insert(updated_target_tag);
411 updated_target_tag.
name.c_str());
415 if (need_to_commit) {
416 success = CommitTransaction();
424 bool SqliteHistory::ListTagsAffectedByRollback(
425 const std::string &target_tag_name, std::vector<Tag> *tags)
const {
428 if (!GetByName(target_tag_name, &target_tag)) {
430 target_tag_name.c_str());
435 if (!list_rollback_tags_->BindTargetTag(target_tag)) {
437 "failed to prepare rollback listing query");
442 return RunListing(tags, list_rollback_tags_.weak_ref());
446 bool SqliteHistory::GetHashes(std::vector<shash::Any> *hashes)
const {
447 assert(database_.IsValid());
450 while (get_hashes_->FetchRow()) {
451 hashes->push_back(get_hashes_->RetrieveHash());
454 return get_hashes_->Reset();
458 void SqliteHistory::TakeDatabaseFileOwnership() {
459 assert(database_.IsValid());
460 database_->TakeFileOwnership();
464 void SqliteHistory::DropDatabaseFileOwnership() {
465 assert(database_.IsValid());
466 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,...)