26 const char *VirtualCatalog::kVirtualPath =
".cvmfs";
27 const char *VirtualCatalog::kSnapshotDirectory =
"snapshots";
28 const int VirtualCatalog::kActionNone = 0x00;
29 const int VirtualCatalog::kActionGenerateSnapshots = 0x01;
30 const int VirtualCatalog::kActionRemove = 0x02;
33 void VirtualCatalog::CreateBaseDirectory() {
37 entry_dir.
mode_ = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH
42 entry_dir.
mtime_ = time(NULL);
49 assert(parent_catalog != virtual_catalog);
54 PathString(
"/" +
string(kVirtualPath)), &entry_parent);
57 parent_catalog->
UpdateEntry(entry_parent,
"/" +
string(kVirtualPath));
65 virtual_catalog->
UpdateEntry(entry_virtual,
"/" +
string(kVirtualPath));
69 void VirtualCatalog::CreateNestedCatalogMarker() {
76 void *empty_compressed;
77 uint64_t sz_empty_compressed;
82 sz_empty_compressed, &file_hash);
83 free(empty_compressed);
85 entry_marker.
mode_ = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
87 entry_marker.
mtime_ = time(NULL);
88 entry_marker.
uid_ = 0;
89 entry_marker.
gid_ = 0;
95 void VirtualCatalog::CreateSnapshotDirectory() {
98 entry_dir.
mode_ = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH
102 entry_dir.
size_ = 97;
103 entry_dir.
mtime_ = time(NULL);
112 void VirtualCatalog::EnsurePresence() {
118 CreateBaseDirectory();
119 CreateNestedCatalogMarker();
120 CreateSnapshotDirectory();
126 void VirtualCatalog::Generate(
int actions) {
127 if (actions & kActionGenerateSnapshots) {
130 if (actions & kActionRemove) {
136 void VirtualCatalog::GenerateSnapshots() {
140 vector<TagId> tags_history;
141 vector<TagId> tags_catalog;
142 GetSortedTagsFromHistory(&tags_history);
143 GetSortedTagsFromCatalog(&tags_catalog);
145 string tag_name_end =
"";
146 if (!tags_history.empty())
147 tag_name_end = std::max(tag_name_end, tags_history.rbegin()->name);
148 if (!tags_catalog.empty())
149 tag_name_end = std::max(tag_name_end, tags_catalog.rbegin()->name);
155 unsigned i_history = 0, i_catalog = 0;
156 const unsigned last_history = tags_history.size() - 1;
157 const unsigned last_catalog = tags_catalog.size() - 1;
158 while ((i_history < last_history) || (i_catalog < last_catalog)) {
159 const TagId t_history = tags_history[i_history];
160 const TagId t_catalog = tags_catalog[i_catalog];
163 if (t_history == t_catalog) {
170 if (t_history.
name == t_catalog.
name) {
171 RemoveSnapshot(t_catalog);
172 InsertSnapshot(t_history);
179 if (t_history.
name < t_catalog.
name) {
180 InsertSnapshot(t_history);
187 RemoveSnapshot(t_catalog);
193 bool VirtualCatalog::ParseActions(
const string &action_desc,
int *actions) {
194 *actions = kActionNone;
195 if (action_desc.empty())
198 vector<string> action_tokens =
SplitString(action_desc,
',');
199 for (
unsigned i = 0; i < action_tokens.size(); ++i) {
200 if (action_tokens[i] ==
"snapshots") {
201 *actions |= kActionGenerateSnapshots;
202 }
else if (action_tokens[i] ==
"remove") {
203 *actions |= kActionRemove;
212 void VirtualCatalog::GetSortedTagsFromHistory(vector<TagId> *tags) {
215 vector<history::History::Tag> tags_history;
218 for (
unsigned i = 0, l = tags_history.size(); i < l; ++i) {
223 tags->push_back(
TagId(tags_history[i].name, tags_history[i].root_hash));
225 std::sort(tags->begin(), tags->end());
229 void VirtualCatalog::GetSortedTagsFromCatalog(vector<TagId> *tags) {
232 assert(virtual_catalog != NULL);
235 for (
unsigned i = 0, l = nested_catalogs.size(); i < l; ++i) {
236 tags->push_back(
TagId(
GetFileName(nested_catalogs[i].mountpoint).ToString(),
237 nested_catalogs[i].hash));
239 std::sort(tags->begin(), tags->end());
243 void VirtualCatalog::InsertSnapshot(
TagId tag) {
248 assert(catalog.IsValid());
249 assert(catalog->root_prefix().IsEmpty());
251 const bool retval = catalog->LookupPath(
PathString(
""), &entry_root);
259 string(kVirtualPath) +
"/" +
string(kSnapshotDirectory));
264 assert(virtual_catalog != NULL);
265 const string mountpoint =
"/" + string(kVirtualPath) +
"/" +
266 string(kSnapshotDirectory) +
"/" + tag.
name;
269 virtual_catalog->
UpdateEntry(entry_bind_mountpoint, mountpoint);
272 const uint64_t catalog_size =
GetFileSize(catalog->database_path());
278 void VirtualCatalog::Remove() {
289 assert(entry_virtual.IsHidden());
291 RemoveRecursively(kVirtualPath);
297 void VirtualCatalog::RemoveRecursively(
const string &directory) {
302 for (
unsigned i = 0; i < listing.size(); ++i) {
303 const string this_path = directory +
"/" + listing[i].name().ToString();
304 if (listing[i].IsDirectory()) {
305 if (!listing[i].IsBindMountpoint())
306 RemoveRecursively(this_path);
308 }
else if (listing[i].IsRegular()) {
309 assert(listing[i].name().ToString() ==
".cvmfscatalog");
318 void VirtualCatalog::RemoveSnapshot(
TagId tag) {
320 "remove snapshot %s (%s) from virtual catalog", tag.
name.c_str(),
322 const string tag_dir =
323 string(kVirtualPath) +
"/" + string(kSnapshotDirectory) +
"/" + tag.
name;
328 assert(virtual_catalog != NULL);
337 :
catalog_mgr_(c), assistant_(d, m, p->stratum0, p->dir_temp) { }
void set_is_bind_mountpoint(const bool val)
ShortString< kDefaultMaxName, 1 > NameString
void AddDirectory(const DirectoryEntryBase &entry, const XattrList &xattrs, const std::string &parent_directory)
NameString GetFileName(const PathString &path)
static const std::string kPreviousHeadTag
void RemoveDirectory(const std::string &directory_path)
std::string ToString(const bool with_suffix=false) const
WritableCatalog * GetHostingCatalog(const std::string &path)
void InsertBindMountpoint(const std::string &mountpoint, const shash::Any content_hash, const uint64_t size)
const history::History * history() const
bool LookupPath(const PathString &path, DirectoryEntry *dirent) const
void RemoveBindMountpoint(const std::string &mountpoint)
assert((mem||(size==0))&&"Out Of Memory")
bool LookupPath(const PathString &path, const LookupOptions options, DirectoryEntry *entry)
const NestedCatalogList & ListNestedCatalogs() const
const unsigned kLookupDefault
catalog::WritableCatalogManager * catalog_mgr_
bool IsTransitionPoint(const std::string &mountpoint)
bool Listing(const PathString &path, DirectoryEntryList *listing, const bool expand_symlink)
std::vector< DirectoryEntry > DirectoryEntryList
virtual bool List(std::vector< Tag > *tags) const =0
vector< string > SplitString(const string &str, char delim)
static const std::string kHeadTag
void RemoveFile(const std::string &file_path)
void set_is_hidden(const bool val)
upload::Spooler * spooler_
void RemoveNestedCatalog(const std::string &mountpoint, const bool merge=true)
void HashMem(const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
std::vector< NestedCatalog > NestedCatalogList
ShortString< kDefaultMaxPath, 0 > PathString
int64_t GetFileSize(const std::string &path)
bool CompressMem2Mem(const void *buf, const int64_t size, void **out_buf, uint64_t *out_size)
void AddFile(const DirectoryEntryBase &entry, const XattrList &xattrs, const std::string &parent_directory)
void CreateNestedCatalog(const std::string &mountpoint)
void UpdateEntry(const DirectoryEntry &entry, const shash::Md5 &path_hash)
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)