5 #include "cvmfs_config.h"
57 const float CatalogDatabase::kLatestSchema = 2.5;
58 const float CatalogDatabase::kLatestSupportedSchema = 2.5;
80 const unsigned CatalogDatabase::kLatestSchemaRevision = 6;
82 bool CatalogDatabase::CheckSchemaCompatibility() {
83 return !( (schema_version() >= 2.0-kSchemaEpsilon) &&
84 (!IsEqualSchema(schema_version(), kLatestSupportedSchema)) &&
85 (!IsEqualSchema(schema_version(), 2.4) ||
86 !IsEqualSchema(kLatestSupportedSchema, 2.5)) );
90 bool CatalogDatabase::LiveSchemaUpgradeIfNecessary() {
93 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 0)) {
96 SqlCatalog sql_upgrade(*
this,
"ALTER TABLE nested_catalogs "
103 set_schema_revision(1);
104 if (!StoreSchemaRevision()) {
110 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 1)) {
113 SqlCatalog sql_upgrade1(*
this,
"ALTER TABLE catalog ADD xattr BLOB;");
115 "INSERT INTO statistics (counter, value) VALUES ('self_xattr', 0);");
117 "INSERT INTO statistics (counter, value) VALUES ('subtree_xattr', 0);");
125 set_schema_revision(2);
126 if (!StoreSchemaRevision()) {
132 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 2)) {
136 "INSERT INTO statistics (counter, value) VALUES "
137 "('self_external', 0);");
139 "INSERT INTO statistics (counter, value) VALUES "
140 "('self_external_file_size', 0);");
142 "INSERT INTO statistics (counter, value) VALUES "
143 "('subtree_external', 0);");
145 "INSERT INTO statistics (counter, value) VALUES "
146 "('subtree_external_file_size', 0);");
154 set_schema_revision(3);
155 if (!StoreSchemaRevision()) {
161 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 3)) {
165 "CREATE TABLE bind_mountpoints (path TEXT, sha1 TEXT, size INTEGER, "
166 "CONSTRAINT pk_bind_mountpoints PRIMARY KEY (path));");
172 set_schema_revision(4);
173 if (!StoreSchemaRevision()) {
180 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 4)) {
184 "INSERT INTO statistics (counter, value) VALUES "
185 "('self_special', 0);");
187 "INSERT INTO statistics (counter, value) VALUES "
188 "('subtree_special', 0);");
194 set_schema_revision(5);
195 if (!StoreSchemaRevision()) {
202 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 5)) {
205 set_schema_revision(6);
206 if (!StoreSchemaRevision()) {
216 bool CatalogDatabase::CreateEmptyDatabase() {
222 "CREATE TABLE catalog "
223 "(md5path_1 INTEGER, md5path_2 INTEGER, parent_1 INTEGER, parent_2 INTEGER,"
224 " hardlinks INTEGER, hash BLOB, size INTEGER, mode INTEGER, mtime INTEGER,"
225 " flags INTEGER, name TEXT, symlink TEXT, uid INTEGER, gid INTEGER, "
227 " CONSTRAINT pk_catalog PRIMARY KEY (md5path_1, md5path_2));").
Execute() &&
229 "CREATE INDEX idx_catalog_parent "
230 "ON catalog (parent_1, parent_2);") .
Execute() &&
232 "CREATE TABLE chunks "
233 "(md5path_1 INTEGER, md5path_2 INTEGER, offset INTEGER, size INTEGER, "
235 " CONSTRAINT pk_chunks PRIMARY KEY (md5path_1, md5path_2, offset, size), "
236 " FOREIGN KEY (md5path_1, md5path_2) REFERENCES "
237 " catalog(md5path_1, md5path_2));") .
Execute() &&
239 "CREATE TABLE nested_catalogs (path TEXT, sha1 TEXT, size INTEGER, "
240 "CONSTRAINT pk_nested_catalogs PRIMARY KEY (path));") .
Execute() &&
249 "CREATE TABLE bind_mountpoints (path TEXT, sha1 TEXT, size INTEGER, "
250 "CONSTRAINT pk_bind_mountpoints PRIMARY KEY (path));") .
Execute() &&
252 "CREATE TABLE statistics (counter TEXT, value INTEGER, "
253 "CONSTRAINT pk_statistics PRIMARY KEY (counter));") .
Execute();
256 PrintSqlError(
"failed to create catalog database tables.");
263 bool CatalogDatabase::InsertInitialValues(
264 const std::string &root_path,
265 const bool volatile_content,
266 const std::string &voms_authz,
274 shash::Md5 root_parent_hash = (root_path ==
"")
279 retval = BeginTransaction();
281 PrintSqlError(
"failed to enter initial filling transaction");
286 if (!this->SetProperty(
"revision", 0)) {
288 "failed to insert default initial values into the newly created "
293 if (volatile_content) {
294 if (!this->SetProperty(
"volatile", 1)) {
295 PrintSqlError(
"failed to insert volatile flag into the newly created "
301 if (!voms_authz.empty()) {
302 if (!SetVOMSAuthz(voms_authz)) {
303 PrintSqlError(
"failed to insert VOMS authz flag into the newly created "
320 PrintSqlError(
"failed to insert root entry into newly created catalog.");
325 counters.
self.directories = 1;
330 PrintSqlError(
"failed to insert initial catalog statistics counters.");
335 if (!root_path.empty()) {
336 if (!this->SetProperty(
"root_prefix", root_path)) {
338 "failed to store root prefix in the newly created catalog.");
344 if (!this->SetProperty(
"last_modified", static_cast<uint64_t>(time(NULL)))) {
345 PrintSqlError(
"failed to store creation timestamp in the new catalog.");
350 retval = CommitTransaction();
352 PrintSqlError(
"failed to commit initial filling transaction");
361 CatalogDatabase::SetVOMSAuthz(
const std::string &voms_authz) {
362 return this->SetProperty(
"voms_authz", voms_authz);
366 double CatalogDatabase::GetRowIdWasteRatio()
const {
368 "SELECT 1.0 - CAST(COUNT(*) AS DOUBLE) / MAX(rowid) "
369 "AS ratio FROM catalog;");
370 const bool retval = rowid_waste_ratio_query.
FetchRow();
396 bool CatalogDatabase::CompactDatabase()
const {
400 BeginTransaction() &&
401 SqlCatalog(*
this,
"CREATE TEMPORARY TABLE duplicate AS "
402 " SELECT * FROM catalog "
403 " ORDER BY rowid ASC;").
Execute() &&
406 " SELECT * FROM duplicate "
407 " ORDER BY rowid").
Execute() &&
409 CommitTransaction() &&
418 unsigned int database_flags = 0;
421 database_flags |= kFlagDirNestedRoot;
423 database_flags |= kFlagDirNestedMountpoint;
425 database_flags |= kFlagDirBindMountpoint;
428 database_flags |= kFlagDir;
429 }
else if (entry.
IsLink()) {
430 database_flags |= kFlagFile | kFlagLink;
432 database_flags |= kFlagFile | kFlagFileSpecial;
434 database_flags |= kFlagFile;
437 database_flags |= kFlagFileChunk;
439 database_flags |= kFlagFileExternal;
441 database_flags |= kFlagDirectIo;
448 database_flags |= kFlagHidden;
450 return database_flags;
455 unsigned *flags)
const
459 *flags |= (algo - 1) << kFlagPosHash;
464 unsigned in_flags = ((7 << kFlagPosHash) & flags) >> kFlagPosHash;
477 ((7 << kFlagPosCompression) & flags) >> kFlagPosCompression;
482 uint32_t SqlDirent::Hardlinks2Linkcount(
const uint64_t hardlinks)
const {
483 return (hardlinks << 32) >> 32;
487 uint32_t SqlDirent::Hardlinks2HardlinkGroup(
const uint64_t hardlinks)
const {
488 return hardlinks >> 32;
492 uint64_t SqlDirent::MakeHardlinks(
const uint32_t hardlink_group,
493 const uint32_t linkcount)
const
496 return (static_cast<uint64_t>(hardlink_group) << 32) | linkcount;
504 void SqlDirent::ExpandSymlink(
LinkString *raw_symlink)
const {
505 const char *c = raw_symlink->
GetChars();
506 const char *cEnd = c+raw_symlink->
GetLength();
507 for (; c < cEnd; ++c) {
515 for (c = raw_symlink->
GetChars(); c < cEnd; ++c) {
516 if ((*c ==
'$') && (c < cEnd-2) && (*(c+1) ==
'(')) {
518 const char *rpar = c;
519 while (rpar < cEnd) {
521 goto expand_symlink_getenv;
529 expand_symlink_getenv:
531 const char *default_separator = c;
532 const char *default_value = rpar;
533 while (default_separator != rpar) {
534 if ((*default_separator ==
':') && (*(default_separator + 1) ==
'-')) {
535 default_value = default_separator+2;
541 const unsigned environ_var_length = default_separator-c;
542 char environ_var[environ_var_length+1];
543 environ_var[environ_var_length] =
'\0';
544 memcpy(environ_var, c, environ_var_length);
545 const char *environ_value = getenv(environ_var);
547 result.
Append(environ_value, strlen(environ_value));
549 const unsigned default_length = rpar-default_value;
550 result.
Append(default_value, default_length);
557 raw_symlink->
Assign(result);
565 bool SqlDirentWrite::BindDirentFields(
const int hash_idx,
566 const int hardlinks_idx,
572 const int symlink_idx,
577 const uint64_t hardlinks =
582 BindHashBlob(hash_idx, entry.
checksum_) &&
583 BindInt64(hardlinks_idx, hardlinks) &&
584 BindInt64(size_idx, entry.
size_) &&
585 BindInt(mode_idx, entry.
mode_) &&
586 BindInt64(uid_idx, entry.
uid_) &&
587 BindInt64(gid_idx, entry.
gid_) &&
588 BindInt64(mtime_idx, entry.
mtime_) &&
589 BindInt(flags_idx, CreateDatabaseFlags(entry)) &&
600 static const char *stmt_lt_2_4 =
601 "SELECT hash, flags, 0 "
603 " WHERE length(hash) > 0;";
605 static const char *stmt_ge_2_4 =
606 "SELECT hash, flags, 0 "
608 " WHERE (length(catalog.hash) > 0) AND "
609 " ((flags & 128) = 0) "
611 "SELECT chunks.hash, catalog.flags, 1 "
614 " ON catalog.md5path_1 = chunks.md5path_1 AND "
615 " catalog.md5path_2 = chunks.md5path_2 "
616 " WHERE (catalog.flags & 128) = 0;";
618 if (database.
schema_version() < 2.4-CatalogDatabase::kSchemaEpsilon) {
619 DeferredInit(database.
sqlite_db(), stmt_lt_2_4);
621 DeferredInit(database.
sqlite_db(), stmt_ge_2_4);
627 const unsigned int db_flags = RetrieveInt(1);
629 shash::Any hash = RetrieveHashBlob(0, hash_algorithm);
630 if (RetrieveInt(2) == 1) {
640 #define DB_FIELDS_LT_V2_1 \
641 "catalog.hash, catalog.inode, catalog.size, " \
642 "catalog.mode, catalog.mtime, catalog.flags, " \
643 "catalog.name, catalog.symlink, catalog.md5path_1, " \
644 "catalog.md5path_2, catalog.parent_1, catalog.parent_2, " \
646 #define DB_FIELDS_GE_V2_1_LT_R2 \
647 "catalog.hash, catalog.hardlinks, catalog.size, " \
648 "catalog.mode, catalog.mtime, catalog.flags, " \
649 "catalog.name, catalog.symlink, catalog.md5path_1, " \
650 "catalog.md5path_2, catalog.parent_1, catalog.parent_2, " \
651 "catalog.rowid, catalog.uid, catalog.gid, " \
653 #define DB_FIELDS_GE_V2_1_GE_R2 \
654 "catalog.hash, catalog.hardlinks, catalog.size, " \
655 "catalog.mode, catalog.mtime, catalog.flags, " \
656 "catalog.name, catalog.symlink, catalog.md5path_1, " \
657 "catalog.md5path_2, catalog.parent_1, catalog.parent_2, " \
658 "catalog.rowid, catalog.uid, catalog.gid, " \
659 "catalog.xattr IS NOT NULL"
661 #define MAKE_STATEMENT(STMT_TMPL, REV) \
662 static const std::string REV = \
663 ReplaceAll(STMT_TMPL, "@DB_FIELDS@", DB_FIELDS_ ## REV)
665 #define MAKE_STATEMENTS(STMT_TMPL) \
666 MAKE_STATEMENT(STMT_TMPL, LT_V2_1); \
667 MAKE_STATEMENT(STMT_TMPL, GE_V2_1_LT_R2); \
668 MAKE_STATEMENT(STMT_TMPL, GE_V2_1_GE_R2)
670 #define DEFERRED_INIT(DB, REV) \
671 DeferredInit((DB).sqlite_db(), (REV).c_str())
673 #define DEFERRED_INITS(DB) \
674 if ((DB).schema_version() < 2.1 - CatalogDatabase::kSchemaEpsilon) { \
675 DEFERRED_INIT((DB), LT_V2_1); \
676 } else if ((DB).schema_revision() < 2) { \
677 DEFERRED_INIT((DB), GE_V2_1_LT_R2); \
679 DEFERRED_INIT((DB), GE_V2_1_GE_R2); \
684 return RetrieveMd5(8, 9);
689 return RetrieveMd5(10, 11);
697 const bool expand_symlink)
const
701 const unsigned database_flags = RetrieveInt(5);
704 (database_flags & kFlagDirNestedMountpoint);
705 const char *name =
reinterpret_cast<const char *
>(RetrieveText(6));
706 const char *symlink =
reinterpret_cast<const char *
>(RetrieveText(7));
709 if (catalog->
schema() < 2.1 - CatalogDatabase::kSchemaEpsilon) {
719 const uint64_t hardlinks = RetrieveInt64(1);
720 result.
linkcount_ = Hardlinks2Linkcount(hardlinks);
726 result.
is_hidden_ = (database_flags & kFlagHidden);
731 RetrieveHashBlob(0, RetrieveHashAlgorithm(database_flags));
733 RetrieveCompressionAlgorithm(database_flags);
739 result.
uid_ = catalog->
MapUid(RetrieveInt64(13));
740 result.
gid_ = catalog->
MapGid(RetrieveInt64(14));
744 result.
mode_ = RetrieveInt(3);
745 result.
size_ = RetrieveInt64(2);
746 result.
mtime_ = RetrieveInt64(4);
753 if (S_ISDIR(result.
mode_)) {
754 result.
mode_ |= 0555;
756 result.
mode_ |= 0444;
769 "WHERE (parent_1 = :p_1) AND (parent_2 = :p_2);");
774 bool SqlListing::BindPathHash(
const struct shash::Md5 &hash) {
775 return BindMd5(1, 2, hash);
784 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
788 bool SqlLookupPathHash::BindPathHash(
const struct shash::Md5 &hash) {
789 return BindMd5(1, 2, hash);
797 MAKE_STATEMENTS(
"SELECT @DB_FIELDS@ FROM catalog WHERE rowid = :rowid;");
802 bool SqlLookupInode::BindRowId(
const uint64_t inode) {
803 return BindInt64(1, inode);
810 SqlLookupDanglingMountpoints::SqlLookupDanglingMountpoints(
813 "JOIN catalog AS c2 "
814 "ON catalog.md5path_1 = c2.parent_1 AND "
815 " catalog.md5path_2 = c2.parent_2 "
816 "WHERE catalog.flags & :nested_mountpoint_flag");
821 const bool success = BindInt64(1, SqlDirent::kFlagDirNestedMountpoint);
832 "SET hash = :hash, size = :size, mode = :mode, mtime = :mtime, "
834 "name = :name, symlink = :symlink, uid = :uid, gid = :gid, xattr = :xattr "
836 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
844 BindInt64(2, entry.
size_) &&
845 BindInt(3, entry.
mode_) &&
846 BindInt64(4, entry.
mtime_) &&
849 BindInt64(7, entry.
uid_) &&
850 BindInt64(8, entry.
gid_));
855 return BindMd5(10, 11, hash);
859 bool SqlDirentTouch::BindXattr(
const XattrList &xattrs) {
860 unsigned char *packed_xattrs;
863 if (packed_xattrs == NULL)
865 return BindBlobTransient(9, packed_xattrs, size);
869 bool SqlDirentTouch::BindXattrEmpty() {
880 static const char *stmt_0_9 =
881 "SELECT '', 0 FROM nested_catalogs;";
882 static const char *stmt_2_5_ge_4 =
883 "SELECT sha1, size FROM nested_catalogs WHERE path=:path "
884 "UNION ALL SELECT sha1, size FROM bind_mountpoints WHERE path=:path;";
885 static const char *stmt_2_5_ge_1_lt_4 =
886 "SELECT sha1, size FROM nested_catalogs WHERE path=:path;";
888 static const char *stmt_2_5_lt_1 =
889 "SELECT sha1, 0 FROM nested_catalogs WHERE path=:path;";
894 DeferredInit(database.
sqlite_db(), stmt_2_5_ge_4);
898 DeferredInit(database.
sqlite_db(), stmt_2_5_ge_1_lt_4);
901 DeferredInit(database.
sqlite_db(), stmt_0_9);
903 DeferredInit(database.
sqlite_db(), stmt_2_5_lt_1);
909 bool SqlNestedCatalogLookup::BindSearchPath(
const PathString &path) {
915 const string hash = string(reinterpret_cast<const char *>(RetrieveText(0)));
922 uint64_t SqlNestedCatalogLookup::GetSize()
const {
923 return RetrieveInt64(1);
930 SqlNestedCatalogListing::SqlNestedCatalogListing(
934 static const char *stmt_0_9 =
935 "SELECT '', '', 0 FROM nested_catalogs;";
936 static const char *stmt_2_5_ge_4 =
937 "SELECT path, sha1, size FROM nested_catalogs "
938 "UNION ALL SELECT path, sha1, size FROM bind_mountpoints;";
939 static const char *stmt_2_5_ge_1_lt_4 =
940 "SELECT path, sha1, size FROM nested_catalogs;";
942 static const char *stmt_2_5_lt_1 =
943 "SELECT path, sha1, 0 FROM nested_catalogs;";
948 DeferredInit(database.
sqlite_db(), stmt_2_5_ge_4);
952 DeferredInit(database.
sqlite_db(), stmt_2_5_ge_1_lt_4);
955 DeferredInit(database.
sqlite_db(), stmt_0_9);
957 DeferredInit(database.
sqlite_db(), stmt_2_5_lt_1);
964 const char *path =
reinterpret_cast<const char *
>(RetrieveText(0));
970 const string hash = string(reinterpret_cast<const char *>(RetrieveText(1)));
977 uint64_t SqlNestedCatalogListing::GetSize()
const {
978 return RetrieveInt64(2);
985 SqlOwnNestedCatalogListing::SqlOwnNestedCatalogListing(
989 static const char *stmt_0_9 =
990 "SELECT '', '', 0 FROM nested_catalogs;";
991 static const char *stmt_2_5_ge_1 =
992 "SELECT path, sha1, size FROM nested_catalogs;";
994 static const char *stmt_2_5_lt_1 =
995 "SELECT path, sha1, 0 FROM nested_catalogs;";
1000 DeferredInit(database.
sqlite_db(), stmt_2_5_ge_1);
1003 DeferredInit(database.
sqlite_db(), stmt_0_9);
1005 DeferredInit(database.
sqlite_db(), stmt_2_5_lt_1);
1012 const char *path =
reinterpret_cast<const char *
>(RetrieveText(0));
1018 const string hash = string(reinterpret_cast<const char *>(RetrieveText(1)));
1025 uint64_t SqlOwnNestedCatalogListing::GetSize()
const {
1026 return RetrieveInt64(2);
1035 "INSERT INTO catalog "
1036 "(md5path_1, md5path_2, parent_1, parent_2, hash, hardlinks, size, mode,"
1038 "mtime, flags, name, symlink, uid, gid, xattr) "
1040 "VALUES (:md5_1, :md5_2, :p_1, :p_2, :hash, :links, :size, :mode, :mtime,"
1041 " :flags, :name, :symlink, :uid, :gid, :xattr);");
1046 return BindMd5(1, 2, hash);
1050 bool SqlDirentInsert::BindParentPathHash(
const shash::Md5 &hash) {
1051 return BindMd5(3, 4, hash);
1056 return BindDirentFields(5, 6, 7, 8, 9, 10, 11, 12, 13, 14, entry);
1061 unsigned char *packed_xattrs;
1063 xattrs.
Serialize(&packed_xattrs, &size);
1064 if (packed_xattrs == NULL)
1065 return BindNull(15);
1066 return BindBlobTransient(15, packed_xattrs, size);
1070 bool SqlDirentInsert::BindXattrEmpty() {
1071 return BindNull(15);
1081 "SET hash = :hash, size = :size, mode = :mode, mtime = :mtime, "
1083 "flags = :flags, name = :name, symlink = :symlink, hardlinks = :hardlinks, "
1085 "uid = :uid, gid = :gid "
1087 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1093 return BindMd5(11, 12, hash);
1098 return BindDirentFields(1, 8, 2, 3, 4, 5, 6, 7, 9, 10, entry);
1107 "DELETE FROM catalog "
1108 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1112 return BindMd5(1, 2, hash);
1128 "UPDATE catalog SET hardlinks = hardlinks + :delta "
1129 "WHERE hardlinks = (SELECT hardlinks from catalog "
1130 "WHERE md5path_1 = :md5_1 AND md5path_2 = :md5_2);");
1135 return BindMd5(2, 3, hash);
1139 bool SqlIncLinkcount::BindDelta(
const int delta) {
1140 return BindInt(1, delta);
1149 "INSERT INTO chunks (md5path_1, md5path_2, offset, size, hash) "
1151 "VALUES (:md5_1, :md5_2, :offset, :size, :hash);");
1156 return BindMd5(1, 2, hash);
1160 bool SqlChunkInsert::BindFileChunk(
const FileChunk &chunk) {
1162 BindInt64(3, chunk.
offset()) &&
1163 BindInt64(4, chunk.
size()) &&
1173 "DELETE FROM chunks "
1174 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1179 return BindMd5(1, 2, hash);
1188 "SELECT offset, size, hash FROM chunks "
1190 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2) "
1192 "ORDER BY offset ASC;");
1197 return BindMd5(1, 2, hash);
1216 "SELECT count(*) FROM chunks "
1218 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2)");
1224 return BindMd5(1, 2, hash);
1228 int SqlChunksCount::GetChunkCount()
const {
1229 return RetrieveInt64(0);
1237 DeferredInit(database.
sqlite_db(),
"SELECT max(hardlinks) FROM catalog;");
1241 uint32_t SqlMaxHardlinkGroup::GetMaxGroupId()
const {
1242 return RetrieveInt64(0) >> 32;
1250 static const char *stmt_ge_2_4 =
1251 "SELECT value from statistics WHERE counter = :counter;";
1252 static const char *stmt_lt_2_4 =
1255 if (database.
schema_version() >= 2.4 - CatalogDatabase::kSchemaEpsilon) {
1257 DeferredInit(database.
sqlite_db(), stmt_ge_2_4);
1260 DeferredInit(database.
sqlite_db(), stmt_lt_2_4);
1265 bool SqlGetCounter::BindCounter(
const std::string &counter) {
1266 if (compat_)
return true;
1267 return BindText(1, counter);
1271 uint64_t SqlGetCounter::GetCounter()
const {
1272 if (compat_)
return 0;
1273 return RetrieveInt64(0);
1282 "UPDATE statistics SET value=value+:val WHERE counter=:counter;");
1286 bool SqlUpdateCounter::BindCounter(
const std::string &counter) {
1287 return BindText(2, counter);
1291 bool SqlUpdateCounter::BindDelta(
const int64_t delta) {
1292 return BindInt64(1, delta);
1301 "INSERT OR REPLACE INTO statistics (counter, value) "
1302 "VALUES (:counter, :value);");
1306 bool SqlCreateCounter::BindCounter(
const std::string &counter) {
1307 return BindText(1, counter);
1311 bool SqlCreateCounter::BindInitialValue(
const int64_t value) {
1312 return BindInt64(2, value);
1320 int hash_mask = 7 << SqlDirent::kFlagPosHash;
1323 StringifyInt(SqlDirent::kFlagPosHash) +
")+1 AS hash_algorithm ";
1325 int compression_mask = 7 << SqlDirent::kFlagPosCompression;
1326 string flags2compression =
1327 " ((flags&" +
StringifyInt(compression_mask) +
") >> " +
1329 "AS compression_algorithm ";
1335 string sql =
"SELECT DISTINCT hash, "
1336 "CASE WHEN flags & " +
StringifyInt(SqlDirent::kFlagFile) +
" THEN " +
1338 "WHEN flags & " +
StringifyInt(SqlDirent::kFlagDir) +
" THEN " +
1340 "AS chunk_type, " + flags2hash +
"," + flags2compression +
1341 "FROM catalog WHERE (hash IS NOT NULL) AND "
1342 "(flags & " +
StringifyInt(SqlDirent::kFlagFileExternal) +
" = 0)";
1343 if (database.
schema_version() >= 2.4 - CatalogDatabase::kSchemaEpsilon) {
1347 ", " + flags2hash +
"," + flags2compression +
1348 "FROM chunks, catalog WHERE "
1349 "chunks.md5path_1=catalog.md5path_1 AND "
1350 "chunks.md5path_2=catalog.md5path_2 AND "
1351 "(catalog.flags & " +
StringifyInt(SqlDirent::kFlagFileExternal) +
1369 *hash = RetrieveHashBlob(0, static_cast<shash::Algorithms>(RetrieveInt(2)),
1370 static_cast<shash::Suffix>(RetrieveInt(1)));
1376 bool SqlAllChunks::Close() {
1386 "SELECT xattr FROM catalog "
1387 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1392 return BindMd5(1, 2, hash);
1397 const unsigned char *packed_xattrs =
1398 reinterpret_cast<const unsigned char *
>(RetrieveBlob(0));
1399 if (packed_xattrs == NULL)
1402 int size = RetrieveBytes(0);
bool InsertIntoDatabase(const CatalogDatabase &database) const
bool IsExternalFile() const
uint64_t MapUid(const uint64_t uid) const
bool IsChunkedFile() const
bool BindDirent(const DirectoryEntry &entry)
void Assign(const char *chars, const unsigned length)
double RetrieveDouble(const int idx_column) const
const char kSuffixMicroCatalog
const shash::Any & content_hash() const
assert((mem||(size==0))&&"Out Of Memory")
float schema_version() const
#define MAKE_STATEMENTS(STMT_TMPL)
unsigned schema_revision() const
#define DEFERRED_INITS(DB)
bool IsNestedCatalogMountpoint() const
bool BindPathHash(const shash::Md5 &hash)
bool IsNestedCatalogRoot() const
zlib::Algorithms compression_algorithm_
const char kSuffixPartial
void Serialize(unsigned char **outbuf, unsigned *size, const std::vector< std::string > *blacklist=NULL) const
const char kSuffixCatalog
bool is_nested_catalog_mountpoint_
zlib::Algorithms compression_algorithm() const
static int Init(const loader::LoaderExports *loader_exports)
void Append(const char *chars, const unsigned length)
string StringifyInt(const int64_t value)
sqlite3 * sqlite_db() const
bool IsBindMountpoint() const
bool IsEqualSchema(const float value, const float compare) const
inode_t GetMangledInode(const uint64_t row_id, const uint64_t hardlink_group) const
static XattrList * Deserialize(const unsigned char *inbuf, const unsigned size)
ShortString< kDefaultMaxPath, 0 > PathString
PathString GetParentPath(const PathString &path)
Any MkFromHexPtr(const HexPtr hex, const char suffix)
unsigned GetLength() const
bool is_nested_catalog_root_
const char * GetChars() const
bool BindParentPathHash(const shash::Md5 &hash)
const shash::Any * checksum_ptr() const
uint64_t MapGid(const uint64_t gid) const
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)