GCC Code Coverage Report


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