CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
shrinkwrap.cc
Go to the documentation of this file.
1 
5 #include <errno.h>
6 #include <getopt.h>
7 #include <pthread.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <time.h>
12 
15 #include "util/concurrency.h"
16 #include "util/logging.h"
17 #include "util/string.h"
18 
19 
20 namespace {
21 
22 struct Params {
23  bool CheckType(const std::string &type) {
24  if ((type == "cvmfs") || (type == "posix"))
25  return true;
26  LogCvmfs(kLogCvmfs, kLogStderr, "Unknown type: %s", type.c_str());
27  return false;
28  }
29 
30  bool Check() {
31  if (!CheckType(src_type) || !CheckType(dst_type))
32  return false;
33 
34  return true;
35  }
36 
37  void Complete() {
38  if (dst_data_dir.empty())
39  dst_data_dir = dst_base_dir + "/.data";
40 
41  if (spec_trace_path.empty())
42  spec_trace_path = repo_name + ".spec";
43 
44  if (num_parallel == 0)
46  }
47 
49  : repo_name()
50  , src_type("cvmfs")
51  , src_base_dir("/cvmfs")
52  , src_config_path("cvmfs.conf:cvmfs.local")
53  , src_data_dir()
54  , dst_type("posix")
55  , dst_config_path()
56  , dst_base_dir("/export/cvmfs")
57  , dst_data_dir()
58  , spec_trace_path()
59  , num_parallel(0)
60  , stat_period(10)
61  , do_garbage_collection(false) { }
62 
63  std::string repo_name;
64  std::string src_type;
65  std::string src_base_dir;
66  std::string src_config_path;
67  std::string src_data_dir;
68  std::string dst_type;
69  std::string dst_config_path;
70  std::string dst_base_dir;
71  std::string dst_data_dir;
72  std::string spec_trace_path;
73  uint64_t num_parallel;
74  uint64_t stat_period;
76 };
77 
78 void Usage() {
79  LogCvmfs(
81  "CernVM File System Shrinkwrapper, version %s\n\n"
82  "This tool takes a cvmfs repository and outputs\n"
83  "to a destination files system.\n"
84  "Usage: cvmfs_shrinkwrap "
85  "[-r][-sbcf][-dxyz][-t][-jrg]\n"
86  "Options:\n"
87  " -r --repo Repository name [required]\n"
88  " -s --src-type Source filesystem type [default:cvmfs]\n"
89  " -b --src-base Source base location [default:/cvmfs/]\n"
90  " -c --src-cache Source cache\n"
91  " -f --src-config Source config [default:cvmfs.conf:cvmfs.local]\n"
92  " -d --dest-type Dest filesystem type [default:posix]\n"
93  " -x --dest-base Dest base [default:/export/cvmfs]\n"
94  " -y --dest-cache Dest cache [default:$BASE/.data]\n"
95  " -z --dest-config Dest config\n"
96  " -t --spec-file Specification file [default=$REPO.spec]\n"
97  " -j --threads Number of concurrent copy threads [default:2*CPUs]\n"
98  " -p --stat-period Frequency of stat prints, 0 disables [default:10]\n"
99  " -g --gc Perform garbage collection on destination\n",
100  CVMFS_VERSION);
101 }
102 
103 } // anonymous namespace
104 
105 int main(int argc, char **argv) {
106  Params params;
107 
108  int c;
109  static struct option long_opts[] = {
110  /* All of the options require an argument */
111  {"help", no_argument, 0, 'h'},
112  {"repo", required_argument, 0, 'r'},
113  {"src-type", required_argument, 0, 's'},
114  {"src-base", required_argument, 0, 'b'},
115  {"src-cache", required_argument, 0, 'c'},
116  {"src-config", required_argument, 0, 'f'},
117  {"dest-type", required_argument, 0, 'd'},
118  {"dest-base", required_argument, 0, 'x'},
119  {"dest-cache", required_argument, 0, 'y'},
120  {"dest-config", required_argument, 0, 'z'},
121  {"spec-file", required_argument, 0, 't'},
122  {"threads", required_argument, 0, 'j'},
123  {"stat-period", required_argument, 0, 'p'},
124  {"gc", no_argument, 0, 'g'},
125  {0, 0, 0, 0}};
126 
127  static const char short_opts[] = "hb:s:r:c:f:d:x:y:t:j:p:g";
128 
129  while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) >= 0) {
130  switch (c) {
131  case 'h':
132  Usage();
133  return 0;
134  case 'r':
135  params.repo_name = optarg;
136  break;
137  case 's':
138  params.src_type = optarg;
139  break;
140  case 'b':
141  params.src_base_dir = optarg;
142  break;
143  case 'c':
144  params.src_data_dir = optarg;
145  break;
146  case 'f':
147  params.src_config_path = optarg;
148  break;
149  case 'd':
150  params.dst_type = optarg;
151  break;
152  case 'x':
153  params.dst_base_dir = optarg;
154  break;
155  case 'y':
156  params.dst_data_dir = optarg;
157  break;
158  case 'z':
159  params.dst_config_path = optarg;
160  break;
161  case 't':
162  params.spec_trace_path = optarg;
163  break;
164  case 'j':
165  if (!String2Uint64Parse(optarg, &params.num_parallel)) {
166  LogCvmfs(
168  "Invalid value passed to 'j': %s : only non-negative integers",
169  optarg);
170  Usage();
171  return 1;
172  }
173  break;
174  case 'g':
175  params.do_garbage_collection = true;
176  break;
177  case 'p':
178  if (!String2Uint64Parse(optarg, &params.stat_period)) {
179  LogCvmfs(
181  "Invalid value passed to 'p': %s : only non-negative integers",
182  optarg);
183  Usage();
184  return 1;
185  }
186  break;
187  case '?':
188  default:
189  Usage();
190  return 1;
191  }
192  }
193 
194  if (!params.Check())
195  return 1;
196  params.Complete();
197 
198  struct fs_traversal *src = shrinkwrap::FindInterface(params.src_type.c_str());
199  if (!src) {
200  return 1;
201  }
202  src->context_ = src->initialize(params.repo_name.c_str(),
203  params.src_base_dir.c_str(),
204  params.src_data_dir.c_str(),
205  params.src_config_path.c_str(),
206  params.num_parallel);
207  if (!src->context_) {
208  LogCvmfs(kLogCvmfs, kLogStderr, "Unable to initialize source");
209  return 1;
210  }
211 
213  params.dst_type.c_str());
214  if (!dest) {
215  return 1;
216  }
217  dest->context_ = dest->initialize(params.repo_name.c_str(),
218  params.dst_base_dir.c_str(),
219  params.dst_data_dir.c_str(),
220  params.dst_config_path.c_str(),
221  params.num_parallel);
222  if (!dest->context_) {
223  LogCvmfs(kLogCvmfs, kLogStderr, "Unable to initialize destination");
224  src->finalize(src->context_);
225  delete src;
226  return 1;
227  }
228 
229  dest->archive_provenance(src->context_, dest->context_);
230 
231  const int result = shrinkwrap::SyncInit(
232  src, dest, "", /* spec_base_dir, unused */
233  params.spec_trace_path.c_str(), params.num_parallel, params.stat_period);
234 
235  src->finalize(src->context_);
236  if (params.do_garbage_collection) {
238  }
239  dest->finalize(dest->context_);
240 
241  delete src;
242  delete dest;
243 
244  return result;
245 }
struct fs_traversal * FindInterface(const char *type)
Definition: fs_traversal.cc:96
unsigned int GetNumberOfCpuCores()
Definition: concurrency.cc:18
bool CheckType(const std::string &type)
Definition: shrinkwrap.cc:23
bool String2Uint64Parse(const std::string &value, uint64_t *result)
Definition: string.cc:257
int main()
Definition: helper_allow.cc:16
int SyncInit(struct fs_traversal *src, struct fs_traversal *dest, const char *base, const char *spec, uint64_t parallel, uint64_t stat_period)
void(* finalize)(struct fs_traversal_context *ctx)
struct fs_traversal_context *(* initialize)(const char *repo, const char *base, const char *data, const char *config, int num_threads)
void(* archive_provenance)(struct fs_traversal_context *src, struct fs_traversal_context *dest)
void Usage()
int GarbageCollect(struct fs_traversal *fs)
struct fs_traversal_context * context_
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545