GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_mgr_ro.cc
Date: 2025-06-22 02:36:02
Exec Total Coverage
Lines: 42 73 57.5%
Branches: 23 96 24.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM file system.
3 */
4
5
6 #include "catalog_mgr_ro.h"
7
8 #include "compression/compression.h"
9 #include "network/download.h"
10 #include "util/exception.h"
11 #include "util/posix.h"
12
13 using namespace std; // NOLINT
14
15 namespace catalog {
16
17 1448 SimpleCatalogManager::SimpleCatalogManager(
18 const shash::Any &base_hash,
19 const std::string &stratum0,
20 const std::string &dir_temp,
21 download::DownloadManager *download_manager,
22 perf::Statistics *statistics,
23 const bool manage_catalog_files,
24 const std::string &dir_cache,
25 1448 const bool copy_to_tmp_dir)
26 : AbstractCatalogManager<Catalog>(statistics)
27 1448 , dir_cache_(dir_cache)
28 1448 , copy_to_tmp_dir_(copy_to_tmp_dir)
29 1448 , base_hash_(base_hash)
30
1/2
✓ Branch 1 taken 1448 times.
✗ Branch 2 not taken.
1448 , stratum0_(stratum0)
31
1/2
✓ Branch 1 taken 1448 times.
✗ Branch 2 not taken.
1448 , dir_temp_(dir_temp)
32 1448 , download_manager_(download_manager)
33
1/2
✓ Branch 2 taken 1448 times.
✗ Branch 3 not taken.
1448 , manage_catalog_files_(manage_catalog_files) {
34
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1448 times.
1448 if (!dir_cache.empty()) {
35 const bool success = MakeCacheDirectories(dir_cache_, 0755);
36
37 if (!success) {
38 PANIC(kLogStderr,
39 "Failure during creation of local cache directory for server. "
40 "Local cache directory: %s",
41 dir_cache_.c_str());
42 }
43 } else {
44 1448 copy_to_tmp_dir_ = false;
45 }
46 1448 }
47
48 1448 LoadReturn SimpleCatalogManager::GetNewRootCatalogContext(
49 CatalogContext *result) {
50
1/2
✓ Branch 2 taken 1448 times.
✗ Branch 3 not taken.
1448 if (result->hash().IsNull()) {
51 1448 result->SetHash(base_hash_);
52 }
53 1448 result->SetRootCtlgLocation(kCtlgLocationServer);
54
1/2
✓ Branch 2 taken 1448 times.
✗ Branch 3 not taken.
1448 result->SetMountpoint(PathString("", 0));
55
56 1448 return kLoadNew;
57 }
58
59 std::string SimpleCatalogManager::CopyCatalogToTempFile(
60 const std::string &cache_path) {
61 std::string tmp_path;
62 FILE *fcatalog = CreateTempFile(dir_temp_ + "/catalog", 0666, "w", &tmp_path);
63 if (!fcatalog) {
64 PANIC(kLogStderr, "failed to create temp file when loading %s",
65 cache_path.c_str());
66 }
67
68 const bool retval = CopyPath2File(cache_path, fcatalog);
69 if (!retval) {
70 unlink(tmp_path.c_str());
71 PANIC(kLogStderr, "failed to read %s", cache_path.c_str());
72 }
73 (void)fclose(fcatalog);
74
75 return tmp_path;
76 }
77
78 /**
79 * Loads a catalog via HTTP from Statum 0 into a temporary file.
80 * See CatalogContext class description for correct usage
81 *
82 * Depending on the initialization of SimpleCatalogManager, it can locally
83 * cache catalogs.
84 *
85 * Independent of the catalog being downloaded or being already locally cached,
86 * for WriteableCatalog it creates a new copy of the catalog in a tmp dir.
87 * This is due to write actions having to be transaction-based and therefore
88 * cannot work on standard file locations for cvmfs - someone else could try to
89 * access them in a non-clean state.
90 *
91 * @return kLoadNew on success
92 */
93 1884 LoadReturn SimpleCatalogManager::LoadCatalogByHash(
94 CatalogContext *ctlg_context) {
95 1884 const shash::Any effective_hash = ctlg_context->hash();
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1884 times.
1884 assert(shash::kSuffixCatalog == effective_hash.suffix);
97
3/6
✓ Branch 1 taken 1884 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1884 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1884 times.
✗ Branch 8 not taken.
3768 const string url = stratum0_ + "/data/" + effective_hash.MakePath();
98
99 FILE *fcatalog;
100
101
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1884 times.
1884 if (UseLocalCache()) {
102 const std::string cache_path =
103 dir_cache_ + "/" + effective_hash.MakePathWithoutSuffix();
104
105 ctlg_context->SetSqlitePath(cache_path);
106
107 // catalog is cached in "cache_dir/" + standard cvmfs file hierarchy
108 if (FileExists(cache_path.c_str())) {
109 if (!copy_to_tmp_dir_) {
110 return kLoadNew;
111 } else { // for writable catalog create copy in dir_temp_
112 std::string tmp_path;
113
114 tmp_path = CopyCatalogToTempFile(cache_path);
115 ctlg_context->SetSqlitePath(tmp_path);
116
117 return kLoadNew;
118 }
119 }
120 }
121
122 // not in local cache; just create a random tmp file for download
123 1884 std::string tmp_path;
124
2/4
✓ Branch 1 taken 1884 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1884 times.
✗ Branch 5 not taken.
1884 fcatalog = CreateTempFile(dir_temp_ + "/catalog", 0666, "w", &tmp_path);
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1884 times.
1884 if (!fcatalog) {
126 PANIC(kLogStderr, "failed to create temp file when loading %s",
127 url.c_str());
128 }
129
1/2
✓ Branch 1 taken 1884 times.
✗ Branch 2 not taken.
1884 ctlg_context->SetSqlitePath(tmp_path);
130
131 1884 cvmfs::FileSink filesink(fcatalog);
132 download::JobInfo download_catalog(&url, true, false, &effective_hash,
133
1/2
✓ Branch 1 taken 1884 times.
✗ Branch 2 not taken.
1884 &filesink);
134
1/2
✓ Branch 1 taken 1884 times.
✗ Branch 2 not taken.
1884 const download::Failures retval = download_manager_->Fetch(&download_catalog);
135
1/2
✓ Branch 1 taken 1884 times.
✗ Branch 2 not taken.
1884 fclose(fcatalog);
136
137
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1869 times.
1884 if (retval != download::kFailOk) {
138 15 unlink(tmp_path.c_str());
139 15 PANIC(kLogStderr, "failed to load %s from Stratum 0 (%d - %s)", url.c_str(),
140 retval, download::Code2Ascii(retval));
141 }
142
143 // for local cache make an atomic rename call to make the file available
144 // in the local cache
145
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1869 times.
1869 if (UseLocalCache()) {
146 const std::string cache_path = dir_cache_ + "/"
147 + effective_hash.MakePathWithoutSuffix();
148 rename(tmp_path.c_str(), cache_path.c_str());
149 ctlg_context->SetSqlitePath(cache_path);
150
151 // for writable catalog make an extra copy that can be modified
152 if (copy_to_tmp_dir_) {
153 const std::string new_tmp_path = CopyCatalogToTempFile(cache_path);
154 ctlg_context->SetSqlitePath(new_tmp_path);
155 }
156 }
157
158 1869 return kLoadNew;
159 1929 }
160
161
162 245 Catalog *SimpleCatalogManager::CreateCatalog(const PathString &mountpoint,
163 const shash::Any &catalog_hash,
164 Catalog *parent_catalog) {
165
1/2
✓ Branch 2 taken 245 times.
✗ Branch 3 not taken.
245 Catalog *new_catalog = new Catalog(mountpoint, catalog_hash, parent_catalog);
166
1/2
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
245 if (manage_catalog_files_) {
167 245 new_catalog->TakeDatabaseFileOwnership();
168 }
169
170 245 return new_catalog;
171 }
172
173 } // namespace catalog
174