CernVM-FS  2.9.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 
13 #include "cvmfs_config.h"
14 #include "logging.h"
17 #include "util/string.h"
18 #include "util_concurrency.h"
19 
20 
21 namespace {
22 
23 struct Params {
24  bool CheckType(const std::string &type) {
25  if ((type == "cvmfs") || (type == "posix")) 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)) return false;
32 
33  return true;
34  }
35 
36  void Complete() {
37  if (dst_data_dir.empty())
38  dst_data_dir = dst_base_dir + "/.data";
39 
40  if (spec_trace_path.empty())
41  spec_trace_path = repo_name + ".spec";
42 
43  if (num_parallel == 0)
45  }
46 
48  : repo_name()
49  , src_type("cvmfs")
50  , src_base_dir("/cvmfs")
51  , src_config_path("cvmfs.conf:cvmfs.local")
52  , src_data_dir()
53  , dst_type("posix")
54  , dst_config_path()
55  , dst_base_dir("/export/cvmfs")
56  , dst_data_dir()
57  , spec_trace_path()
58  , num_parallel(0)
59  , stat_period(10)
60  , do_garbage_collection(false)
61  { }
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() {
80  "CernVM File System Shrinkwrapper, version %s\n\n"
81  "This tool takes a cvmfs repository and outputs\n"
82  "to a destination files system.\n"
83  "Usage: cvmfs_shrinkwrap "
84  "[-r][-sbcf][-dxyz][-t][-jrg]\n"
85  "Options:\n"
86  " -r --repo Repository name [required]\n"
87  " -s --src-type Source filesystem type [default:cvmfs]\n"
88  " -b --src-base Source base location [default:/cvmfs/]\n"
89  " -c --src-cache Source cache\n"
90  " -f --src-config Source config [default:cvmfs.conf:cvmfs.local]\n"
91  " -d --dest-type Dest filesystem type [default:posix]\n"
92  " -x --dest-base Dest base [default:/export/cvmfs]\n"
93  " -y --dest-cache Dest cache [default:$BASE/.data]\n"
94  " -z --dest-config Dest config\n"
95  " -t --spec-file Specification file [default=$REPO.spec]\n"
96  " -j --threads Number of concurrent copy threads [default:2*CPUs]\n"
97  " -p --stat-period Frequency of stat prints, 0 disables [default:10]\n"
98  " -g --gc Perform garbage collection on destination\n",
99  VERSION);
100 }
101 
102 } // anonymous namespace
103 
104 int main(int argc, char **argv) {
105  Params params;
106 
107  int c;
108  static struct option long_opts[] = {
109  /* All of the options require an argument */
110  {"help", no_argument, 0, 'h'},
111  {"repo", required_argument, 0, 'r'},
112  {"src-type", required_argument, 0, 's'},
113  {"src-base", required_argument, 0, 'b'},
114  {"src-cache", required_argument, 0, 'c'},
115  {"src-config", required_argument, 0, 'f'},
116  {"dest-type", required_argument, 0, 'd'},
117  {"dest-base", required_argument, 0, 'x'},
118  {"dest-cache", required_argument, 0, 'y'},
119  {"dest-config", required_argument, 0, 'z'},
120  {"spec-file", required_argument, 0, 't'},
121  {"threads", required_argument, 0, 'j'},
122  {"stat-period", required_argument, 0, 'p'},
123  {"gc", no_argument, 0, 'g'},
124  {0, 0, 0, 0}
125  };
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)) {
167  "Invalid value passed to 'j': %s : only non-negative integers",
168  optarg);
169  Usage();
170  return 1;
171  }
172  break;
173  case 'g':
174  params.do_garbage_collection = true;
175  break;
176  case 'p':
177  if (!String2Uint64Parse(optarg, &params.stat_period)) {
179  "Invalid value passed to 'p': %s : only non-negative integers",
180  optarg);
181  Usage();
182  return 1;
183  }
184  break;
185  case '?':
186  default:
187  Usage();
188  return 1;
189  }
190  }
191 
192  if (!params.Check()) return 1;
193  params.Complete();
194 
195  struct fs_traversal *src = shrinkwrap::FindInterface(params.src_type.c_str());
196  if (!src) {
197  return 1;
198  }
199  src->context_ = src->initialize(
200  params.repo_name.c_str(),
201  params.src_base_dir.c_str(),
202  params.src_data_dir.c_str(),
203  params.src_config_path.c_str(),
204  params.num_parallel);
205  if (!src->context_) {
206  LogCvmfs(kLogCvmfs, kLogStderr, "Unable to initialize source");
207  return 1;
208  }
209 
210  struct fs_traversal *dest =
211  shrinkwrap::FindInterface(params.dst_type.c_str());
212  if (!dest) {
213  return 1;
214  }
215  dest->context_ = dest->initialize(
216  params.repo_name.c_str(),
217  params.dst_base_dir.c_str(),
218  params.dst_data_dir.c_str(),
219  params.dst_config_path.c_str(),
220  params.num_parallel);
221  if (!dest->context_) {
222  LogCvmfs(kLogCvmfs, kLogStderr, "Unable to initialize destination");
223  src->finalize(src->context_);
224  delete src;
225  return 1;
226  }
227 
228  dest->archive_provenance(src->context_, dest->context_);
229 
230  int result = shrinkwrap::SyncInit(
231  src,
232  dest,
233  "", /* spec_base_dir, unused */
234  params.spec_trace_path.c_str(),
235  params.num_parallel,
236  params.stat_period);
237 
238  src->finalize(src->context_);
239  if (params.do_garbage_collection) {
241  }
242  dest->finalize(dest->context_);
243 
244  delete src;
245  delete dest;
246 
247  return result;
248 }
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
struct fs_traversal * FindInterface(const char *type)
unsigned int GetNumberOfCpuCores()
bool CheckType(const std::string &type)
Definition: shrinkwrap.cc:24
bool String2Uint64Parse(const std::string &value, uint64_t *result)
Definition: string.cc:243
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_