42 char const **char_a = (
char const **)a;
43 char const **char_b = (
char const **)b;
45 return strcmp(*char_a, *char_b);
48 namespace shrinkwrap {
61 FileCopy(
char *src,
char *dest) : src(strdup(src)), dest(strdup(dest)) { }
74 : dir(strdup(dir)), recursive(recursive) { }
87 pthread_mutex_t
lock_pipe = PTHREAD_MUTEX_INITIALIZER;
97 if (!strcmp(type,
"posix")) {
99 }
else if (!strcmp(type,
"cvmfs")) {
162 const char *src_name,
164 const char *dest_name,
168 size_t bytes_transferred = 0;
177 src_name, errno, strerror(errno));
185 dest_name, errno, strerror(errno));
193 size_t actual_read = 0;
194 retval = src_fs->
do_fread(src, buffer,
sizeof(buffer), &actual_read);
201 bytes_transferred += actual_read;
203 retval = dest_fs->
do_fwrite(dest, buffer, actual_read);
221 src_name, errno, strerror(errno));
229 dest_name, errno, strerror(errno));
244 size_t len = 2 + strlen(dir) + strlen(entry);
245 char *path =
reinterpret_cast<char *
>(smalloc(len));
246 snprintf(path, len,
"%s/%s", dir, entry);
275 location = (*iter) + 1;
282 if (dir_list && dir_list[location]) {
285 return getNext(fs, dir, dir_list, entry, iter, st, get_hash, is_src,
288 if (entry && !
updateStat(fs, *entry, st, get_hash)) {
289 return getNext(fs, dir, dir_list, entry, iter, st, get_hash, is_src,
297 switch ((*st)->st_mode & S_IFMT) {
341 FileCopy next_copy(src_ident, dest_data);
346 if (!
copyFile(src, src_ident, dest, dest_data, pstats)) {
348 entry, dest_data, errno, strerror(errno));
364 dest_data, errno, strerror(errno));
379 if (errno == EEXIST) {
388 entry, errno, strerror(errno));
396 dirs_.push_back(
new RecDir(dir, recursive));
409 return strcmp(src, dest);
421 char **src_dir = NULL;
423 ssize_t src_iter = -1;
424 char *src_entry = NULL;
428 char **dest_dir = NULL;
430 ssize_t dest_iter = -1;
431 char *dest_entry = NULL;
434 qsort(dest_dir, dest_len,
sizeof(
char *),
strcmp_list);
439 getNext(src, dir, src_dir, &src_entry, &src_iter, &src_st,
true,
true,
443 getNext(dest, dir, dest_dir, &dest_entry, &dest_iter, &dest_st,
false,
451 if (!src_entry && !dest_entry)
470 switch (src_st->
st_mode & S_IFMT) {
472 if (!
handle_file(src, src_st, dest, dest_st, src_entry, pstats))
476 if (!
handle_dir(src, src_st, dest, dest_st, src_entry))
478 if (result && recursive)
487 "Traversal failed to symlink %s->%s : %d : %s", src_entry,
498 "Encountered unknown file type '%d' for source file %s",
499 src_st->
st_mode & S_IFMT, src_entry);
504 switch (dest_st->
st_mode & S_IFMT) {
518 if (!
Sync(dest_entry, src, dest,
true, pstats)) {
530 "Encountered unknown file type '%d' for destination file %s",
531 dest_st->
st_mode & S_IFMT, dest_entry);
553 uint64_t last_print_time) {
555 dirs_.push_back(
new RecDir(
"",
true));
557 while (!
dirs_.empty()) {
558 RecDir *next_dir =
dirs_.back();
561 if (!
Sync(next_dir->dir, src, dest, next_dir->recursive, pstats)) {
604 if (next_copy.IsTerminateJob())
607 if (!next_copy.src || !next_copy.dest) {
615 files_transferred->
Inc();
620 free(next_copy.dest);
630 "Number of files from source repository");
632 "Number of directories from source repository");
634 "Number of symlinks from source repository");
636 "Byte count of projected repository");
638 "Number of file system entries processed in the source");
641 "Number of file system entries processed in the destination");
644 "Number of data files transferred from source to destination");
646 "Bytes transferred from source to destination");
648 "Number of files not copied due to deduplication");
650 "Number of bytes not copied due to deduplication");
659 uint64_t stat_period) {
668 pthread_t *workers = NULL;
675 workers =
reinterpret_cast<pthread_t *
>(
678 specificWorkerContexts =
reinterpret_cast<
692 specificWorkerContexts[i].
mwc = mwc;
694 int retval = pthread_create(
696 static_cast<void *>(&(specificWorkerContexts[i])));
706 uint64_t last_print_time = 0;
708 int result = !
SyncFull(src, dest, pstats, last_print_time);
724 FileCopy terminate_workers;
728 int retval = pthread_join(workers[i], NULL);
733 delete specificWorkerContexts;
751 (end_time - start_time));
Counter * Register(const std::string &name, const std::string &desc)
bool SyncFull(struct fs_traversal *src, struct fs_traversal *dest, perf::Statistics *pstats, uint64_t last_print_time)
struct fs_traversal * FindInterface(const char *type)
int(* do_fopen)(void *file_ctx, fs_open_type op_mode)
#define SHRINKWRAP_STAT_DATA_BYTES_DEDUPED
bool cvmfs_attr_cmp(struct cvmfs_attr *src, struct cvmfs_attr *dest, struct fs_traversal *dest_fs)
void list_src_dir(struct fs_traversal *src, const char *dir, char ***buf, size_t *len)
#define SHRINKWRAP_STAT_COUNT_FILE
void cvmfs_attr_free(struct cvmfs_attr *attr)
bool getNext(struct fs_traversal *fs, const char *dir, char **dir_list, char **entry, ssize_t *iter, struct cvmfs_attr **st, bool get_hash, bool is_src, perf::Statistics *pstats)
#define SHRINKWRAP_STAT_DATA_FILES
static void * MainWorker(void *data)
int(* set_meta)(struct fs_traversal_context *ctx, const char *path, const struct cvmfs_attr *stat)
bool(* is_hash_consistent)(struct fs_traversal_context *ctx, const struct cvmfs_attr *stat)
static SpecTree * Create(const std::string &path)
#define SHRINKWRAP_STAT_COUNT_SYMLINK
FileCopy(char *src, char *dest)
pthread_mutex_t lock_pipe
struct fs_traversal * posix_get_interface()
struct fs_traversal * libcvmfs_get_interface()
#define SHRINKWRAP_STAT_COUNT_DIR
assert((mem||(size==0))&&"Out Of Memory")
int(* do_unlink)(struct fs_traversal_context *ctx, const char *path)
bool handle_file(struct fs_traversal *src, struct cvmfs_attr *src_st, struct fs_traversal *dest, struct cvmfs_attr *dest_st, const char *entry, perf::Statistics *pstats)
int(* garbage_collector)(struct fs_traversal_context *ctx)
int strcmp_list(const void *a, const void *b)
bool IsTerminateJob() const
struct fs_traversal * dest_fs
int(* do_rmdir)(struct fs_traversal_context *ctx, const char *path)
void MakePipe(int pipe_fd[2])
void *(* get_handle)(struct fs_traversal_context *ctx, const char *identifier)
#define SHRINKWRAP_STAT_DATA_BYTES
perf::Statistics * GetSyncStatTemplate()
void(* do_ffree)(void *file_ctx)
int SyncInit(struct fs_traversal *src, struct fs_traversal *dest, const char *base, const char *spec, uint64_t parallel, uint64_t stat_period)
uint64_t stat_update_period_
void cvmfs_list_free(char **buf)
Counter * Lookup(const std::string &name) const
int(* touch)(struct fs_traversal_context *ctx, const struct cvmfs_attr *stat)
int(* do_symlink)(struct fs_traversal_context *ctx, const char *src, const char *dest, const struct cvmfs_attr *stat_info)
struct fs_traversal * src_fs
perf::Statistics * pstats
int(* do_link)(struct fs_traversal_context *ctx, const char *path, const char *identifier)
void(* list_dir)(struct fs_traversal_context *ctx, const char *dir, char ***buf, size_t *len)
#define SHRINKWRAP_STAT_ENTRIES_SRC
bool updateStat(struct fs_traversal *fs, const char *entry, struct cvmfs_attr **st, bool get_hash)
void add_dir_for_sync(const char *dir, bool recursive)
int robust_strcmp(const char *src, const char *dest)
int(* do_fclose)(void *file_ctx)
int(* get_stat)(struct fs_traversal_context *ctx, const char *path, struct cvmfs_attr *stat, bool get_hash)
int64_t Xadd(const int64_t delta)
#define SHRINKWRAP_STAT_ENTRIES_DEST
int(* do_fwrite)(void *file_ctx, const char *buff, size_t len)
bool copyFile(struct fs_traversal *src_fs, const char *src_name, struct fs_traversal *dest_fs, const char *dest_name, perf::Statistics *pstats)
std::string PrintList(const PrintOptions print_options)
int(* do_fread)(void *file_ctx, char *buff, size_t len, size_t *read_len)
void SafeSleepMs(const unsigned ms)
int(* do_mkdir)(struct fs_traversal_context *ctx, const char *path, const struct cvmfs_attr *stat)
RecDir(const char *dir, bool recursive)
bool IsMatching(std::string path)
#define SHRINKWRAP_STAT_DATA_FILES_DEDUPED
int ListDir(const char *dir, char ***buf, size_t *len)
char *(* get_identifier)(struct fs_traversal_context *ctx, const struct cvmfs_attr *stat)
char * get_full_path(const char *dir, const char *entry)
struct MainWorkerContext * mwc
void WritePipe(int fd, const void *buf, size_t nbyte)
void ReadPipe(int fd, void *buf, size_t nbyte)
void ClosePipe(int pipe_fd[2])
struct cvmfs_attr * cvmfs_attr_init()
bool handle_dir(struct fs_traversal *src, struct cvmfs_attr *src_st, struct fs_traversal *dest, struct cvmfs_attr *dest_st, const char *entry)
#define SHRINKWRAP_STAT_COUNT_BYTE
struct fs_traversal_context * context_
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)