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 |
38 S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
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() {
75 void *empty_compressed;
76 uint64_t sz_empty_compressed;
78 NULL, 0, &empty_compressed, &sz_empty_compressed);
81 sz_empty_compressed, &file_hash);
82 free(empty_compressed);
84 entry_marker.
mode_ = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
86 entry_marker.
mtime_ = time(NULL);
87 entry_marker.
uid_ = 0;
88 entry_marker.
gid_ = 0;
94 void VirtualCatalog::CreateSnapshotDirectory() {
97 entry_dir.
mode_ = S_IFDIR |
98 S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
101 entry_dir.
size_ = 97;
102 entry_dir.
mtime_ = time(NULL);
111 void VirtualCatalog::EnsurePresence() {
117 CreateBaseDirectory();
118 CreateNestedCatalogMarker();
119 CreateSnapshotDirectory();
125 void VirtualCatalog::Generate(
int actions) {
126 if (actions & kActionGenerateSnapshots) {
129 if (actions & kActionRemove) {
135 void VirtualCatalog::GenerateSnapshots() {
139 vector<TagId> tags_history;
140 vector<TagId> tags_catalog;
141 GetSortedTagsFromHistory(&tags_history);
142 GetSortedTagsFromCatalog(&tags_catalog);
144 string tag_name_end =
"";
145 if (!tags_history.empty())
146 tag_name_end = std::max(tag_name_end, tags_history.rbegin()->name);
147 if (!tags_catalog.empty())
148 tag_name_end = std::max(tag_name_end, tags_catalog.rbegin()->name);
154 unsigned i_history = 0, i_catalog = 0;
155 unsigned last_history = tags_history.size() - 1;
156 unsigned last_catalog = tags_catalog.size() - 1;
157 while ((i_history < last_history) || (i_catalog < last_catalog)) {
158 TagId t_history = tags_history[i_history];
159 TagId t_catalog = tags_catalog[i_catalog];
162 if (t_history == t_catalog) {
169 if (t_history.
name == t_catalog.
name) {
170 RemoveSnapshot(t_catalog);
171 InsertSnapshot(t_history);
178 if (t_history.
name < t_catalog.
name) {
179 InsertSnapshot(t_history);
186 RemoveSnapshot(t_catalog);
192 bool VirtualCatalog::ParseActions(
193 const string &action_desc,
196 *actions = kActionNone;
197 if (action_desc.empty())
200 vector<string> action_tokens =
SplitString(action_desc,
',');
201 for (
unsigned i = 0; i < action_tokens.size(); ++i) {
202 if (action_tokens[i] ==
"snapshots") {
203 *actions |= kActionGenerateSnapshots;
204 }
else if (action_tokens[i] ==
"remove") {
205 *actions |= kActionRemove;
214 void VirtualCatalog::GetSortedTagsFromHistory(vector<TagId> *tags) {
217 vector<history::History::Tag> tags_history;
220 for (
unsigned i = 0, l = tags_history.size(); i < l; ++i) {
226 tags->push_back(
TagId(tags_history[i].name, tags_history[i].root_hash));
228 std::sort(tags->begin(), tags->end());
232 void VirtualCatalog::GetSortedTagsFromCatalog(vector<TagId> *tags) {
235 assert(virtual_catalog != NULL);
238 for (
unsigned i = 0, l = nested_catalogs.size(); i < l; ++i) {
239 tags->push_back(
TagId(
GetFileName(nested_catalogs[i].mountpoint).ToString(),
240 nested_catalogs[i].hash));
242 std::sort(tags->begin(), tags->end());
246 void VirtualCatalog::InsertSnapshot(
TagId tag) {
251 assert(catalog.IsValid());
252 assert(catalog->root_prefix().IsEmpty());
254 bool retval = catalog->LookupPath(
PathString(
""), &entry_root);
261 string(kVirtualPath) +
"/" +
string(kSnapshotDirectory));
266 assert(virtual_catalog != NULL);
268 "/" + string(kVirtualPath) +
"/" + string(kSnapshotDirectory) +
"/" +
272 virtual_catalog->
UpdateEntry(entry_bind_mountpoint, mountpoint);
275 uint64_t catalog_size =
GetFileSize(catalog->database_path());
281 void VirtualCatalog::Remove() {
292 assert(entry_virtual.IsHidden());
294 RemoveRecursively(kVirtualPath);
300 void VirtualCatalog::RemoveRecursively(
const string &directory) {
304 for (
unsigned i = 0; i < listing.size(); ++i) {
305 string this_path = directory +
"/" + listing[i].name().ToString();
306 if (listing[i].IsDirectory()) {
307 if (!listing[i].IsBindMountpoint())
308 RemoveRecursively(this_path);
310 }
else if (listing[i].IsRegular()) {
311 assert(listing[i].name().ToString() ==
".cvmfscatalog");
320 void VirtualCatalog::RemoveSnapshot(
TagId tag) {
322 "remove snapshot %s (%s) from virtual catalog",
325 string(kVirtualPath) +
"/" + string(kSnapshotDirectory) +
"/" + tag.
name;
330 assert(virtual_catalog != NULL);
335 VirtualCatalog::VirtualCatalog(
341 , 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,...)