static gboolean checksum_start(int argc, char **argv) { GError *error = NULL; gboolean sign = FALSE; g_message("checksum start"); if (r_context()->certpath != NULL && r_context()->keypath != NULL) { sign = TRUE; } else if (r_context()->certpath != NULL || r_context()->keypath != NULL) { g_warning("Either both or none of cert and key files must be provided"); r_exit_status = 1; goto out; } if (argc != 3) { g_warning("A directory name must be provided"); r_exit_status = 1; goto out; } g_message("updating checksums for: %s", argv[2]); if (!update_manifest(argv[2], sign, &error)) { g_warning("Failed to update manifest: %s", error->message); g_clear_error(&error); r_exit_status = 1; } out: return TRUE; }
static gboolean bundle_start(int argc, char **argv) { GError *ierror = NULL; g_debug("bundle start"); if (r_context()->certpath == NULL || r_context()->keypath == NULL) { g_warning("cert and key files must be provided"); r_exit_status = 1; goto out; } if (argc < 3) { g_warning("an input directory name must be provided"); r_exit_status = 1; goto out; } if (argc != 4) { g_warning("an output bundle name must be provided"); r_exit_status = 1; goto out; } g_print("input directory: %s\n", argv[2]); g_print("output bundle: %s\n", argv[3]); if (!update_manifest(argv[2], FALSE, &ierror)) { g_warning("failed to update manifest: %s", ierror->message); r_exit_status = 1; goto out; } if (!create_bundle(argv[3], argv[2], &ierror)) { g_warning("failed to create bundle: %s", ierror->message); r_exit_status = 1; goto out; } out: return TRUE; }
void close_har() { sds fname = sdsdup(destor.working_directory); fname = sdscat(fname, "recipes/bv"); char s[20]; sprintf(s, "%d", jcr.id); fname = sdscat(fname, s); fname = sdscat(fname, ".sparse"); FILE* fp = fopen(fname, "w"); if (!fp) { fprintf(stderr, "Can not create sparse file"); perror("The reason is"); exit(1); } jcr.total_container_num = g_hash_table_size(container_utilization_monitor); GSequence *seq = g_sequence_new(NULL); int64_t total_size = 0; int64_t sparse_size = 0; /* collect sparse containers */ GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, container_utilization_monitor); while (g_hash_table_iter_next(&iter, &key, &value)) { struct containerRecord* cr = (struct containerRecord*) value; total_size += cr->size; if((1.0*cr->size/(CONTAINER_SIZE - CONTAINER_META_SIZE)) < destor.rewrite_har_utilization_threshold){ /* It is sparse */ if (inherited_sparse_containers && g_hash_table_lookup(inherited_sparse_containers, &cr->cid)) /* It is an inherited sparse container */ jcr.inherited_sparse_num++; jcr.sparse_container_num++; sparse_size += cr->size; g_sequence_insert_sorted(seq, cr, g_record_cmp, NULL); } } /* * If the sparse size is too large, * we need to trim the sequence to control the rewrite ratio. * We use sparse_size/total_size to estimate the rewrite ratio of next backup. * However, the estimation is inaccurate (generally over-estimating), since: * 1. the sparse size is not an accurate indicator of utilization for next backup. * 2. self-references. */ while(destor.rewrite_har_rewrite_limit < 1 && sparse_size*1.0/total_size > destor.rewrite_har_rewrite_limit){ /* * The expected rewrite ratio exceeds the limit. * We trim the last several records in the sequence. * */ GSequenceIter* iter = g_sequence_iter_prev(g_sequence_get_end_iter(seq)); struct containerRecord* r = g_sequence_get(iter); NOTICE("Trim sparse container %lld", r->cid); sparse_size -= r->size; g_sequence_remove(iter); } GSequenceIter* sparse_iter = g_sequence_get_begin_iter(seq); while(sparse_iter != g_sequence_get_end_iter(seq)){ struct containerRecord* r = g_sequence_get(sparse_iter); fprintf(fp, "%lld %d\n", r->cid, r->size); sparse_iter = g_sequence_iter_next(sparse_iter); } fclose(fp); NOTICE("Record %d sparse containers, and %d of them are inherited", g_sequence_get_length(seq), jcr.inherited_sparse_num); g_sequence_free(seq); sdsfree(fname); /* CMA: update the backup times in manifest */ update_manifest(container_utilization_monitor); }