int dnet_check(struct dnet_node *n, struct dnet_meta_container *mc, struct dnet_bulk_array *bulk_array, int need_merge, struct dnet_check_params *params) { int err = 0; struct dnet_session *s = dnet_session_create(n); dnet_session_set_groups(s, (int *)&n->id.group_id, 1); dnet_log(n, DNET_LOG_DEBUG, "need_merge = %d, mc.size = %d\n", need_merge, mc->size); if (need_merge) { err = dnet_check_merge(s, mc); dnet_log(n, DNET_LOG_DEBUG, "err=%d\n", err); if (!err) dnet_merge_remove_local(n, &mc->id, 0); } else { err = dnet_check_copies(n, mc, bulk_array, params); } return err; }
int main(int argc, char *argv[]) { int ch, err; struct dnet_node *n = NULL; struct dnet_config cfg; char *remote_addr = NULL; int remote_port = -1; int remote_family = -1; char *logfile = default_log; int daemonize = 0; FILE *log = NULL; struct dnet_check_request r, *req, *req2; struct tm tm; char *file = NULL; int group_num = 0, *groups; char *ns = NULL; int nsize = 0; struct dnet_session *s; memset(&cfg, 0, sizeof(struct dnet_config)); cfg.wait_timeout = INT_MAX; check_logger.log_level = DNET_LOG_INFO; cfg.check_timeout = 60; memset(&tm, 0, sizeof(tm)); memset(&r, 0, sizeof(r)); r.thread_num = 1; while ((ch = getopt(argc, argv, "b:B:DN:f:n:t:u:U:MRm:w:l:dr:g:h")) != -1) { switch (ch) { case 'b': r.blob_start = atoi(optarg); break; case 'B': r.blob_num = atoi(optarg); break; case 'N': ns = optarg; nsize = strlen(optarg); break; case 'f': file = optarg; break; case 'n': r.thread_num = atoi(optarg); if (r.thread_num > 1) fprintf(stderr, "You are going to run your recovery process with %d threads, " "this can heavily screw up your system performance.\n", r.thread_num); break; case 't': if (!strptime(optarg, "%F %T", &tm)) { fprintf(stderr, "Invalid timestamp string in -t\n"); check_usage(argv[0]); return -EINVAL; } r.timestamp = mktime(&tm); break; case 'u': if (!strptime(optarg, "%F %T", &tm)) { fprintf(stderr, "Invalid timestamp string in -u\n"); check_usage(argv[0]); return -EINVAL; } r.updatestamp_start = mktime(&tm); break; case 'U': if (!strptime(optarg, "%F %T", &tm)) { fprintf(stderr, "Invalid timestamp string in -U\n"); check_usage(argv[0]); return -EINVAL; } r.updatestamp_stop = mktime(&tm); break; case 'D': r.flags |= DNET_CHECK_DRY_RUN; break; case 'M': r.flags |= DNET_CHECK_MERGE; break; // case 'F': // r.flags |= DNET_CHECK_FULL; // break; case 'R': r.flags |= DNET_CHECK_DELETE; break; case 'm': check_logger.log_level = strtoul(optarg, NULL, 0); break; case 'w': cfg.check_timeout = cfg.wait_timeout = atoi(optarg); break; case 'l': logfile = optarg; break; case 'd': daemonize = 1; break; case 'r': err = dnet_parse_addr(optarg, &remote_port, &remote_family); if (err) return err; remote_addr = optarg; break; case 'g': group_num = dnet_parse_groups(optarg, &groups); if (group_num <= 0) return -1; break; case 'h': default: check_usage(argv[0]); return -1; } } if (!remote_addr) { fprintf(stderr, "No remote node specified to route requests.\n"); return -ENOENT; } log = fopen(logfile, "a"); if (!log) { err = -errno; fprintf(stderr, "Failed to open log file %s: %s.\n", logfile, strerror(errno)); return err; } if (daemonize) { if (logfile == default_log) { fprintf(stderr, "You should specify log file for daemon mode\n"); } else { dnet_background(); } } check_logger.log_private = log; check_logger.log = dnet_common_log; cfg.log = &check_logger; n = dnet_node_create(&cfg); if (!n) return -1; err = dnet_add_state(n, remote_addr, remote_port, remote_family, DNET_CFG_NO_ROUTE_LIST); if (err) return err; s = dnet_session_create(n); if (!s) return -ENOMEM; err = dnet_session_set_ns(s, ns, nsize); if (err) return err; req = &r; if (file) { req = dnet_check_gen_request(s, &r, file); if (!req) return -EINVAL; } if (group_num > 0) { req2 = malloc(sizeof(struct dnet_check_request) + req->obj_num * sizeof(struct dnet_id) + group_num * sizeof(int)); if (!req2) return -ENOMEM; memcpy(req2, req, sizeof(struct dnet_check_request) + req->obj_num * sizeof(struct dnet_id)); memcpy((char *)req2 + sizeof(struct dnet_check_request) + req->obj_num * sizeof(struct dnet_id), groups, group_num * sizeof(int)); req2->group_num = group_num; req = req2; } return dnet_request_check(s, req); }
static int dnet_bulk_check_complete_single(struct dnet_net_state *state, struct dnet_bulk_id *ids, int remote_group, struct dnet_bulk_check_priv *p) { struct dnet_session *s = dnet_session_create(state->n); struct dnet_meta_container mc; struct dnet_meta_container temp_mc; struct dnet_meta_update *mu; struct dnet_meta *mg; struct dnet_id id; char *tmpdata = NULL; int *groups, group_num = 1; int err = -EINVAL, error = 0; int i = 0; int my_group, lastest_group = -1; struct dnet_meta_update lastest_mu, my_mu; struct timeval current_ts; int removed_in_all = 1, updated = 0; int lastest = 0; uint64_t cflags = 0; uint64_t ioflags = 0; my_group = state->n->id.group_id; dnet_log(state->n, DNET_LOG_DEBUG, "BULK: checking ID %s\n", dnet_dump_id_str(ids->id.id)); err = -ENOENT; error = 0; dnet_setup_id(&mc.id, my_group, ids->id.id); err = state->n->cb->meta_read(state->n->cb->command_private, &ids->id, &mc.data); if (err <= 0) { if (err == 0) err = -ENOENT; goto err_out_continue; } mc.size = err; /* Set current group meta_update as lastest_mu */ if (!dnet_get_meta_update(state->n, &mc, &my_mu)) { dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: meta_update structure doesn't exist for group %d\n", dnet_dump_id_str(ids->id.id), my_group); err = -ENOENT; goto err_out_kcfree; } dnet_convert_meta_update(&my_mu); memcpy(&lastest_mu, &my_mu, sizeof(struct dnet_meta_update)); lastest_group = my_group; /* Get group list */ if (p->group_num) { /* groups came from dnet_check utility */ groups = p->groups; group_num = p->group_num; } else { mg = dnet_meta_search(state->n, &mc, DNET_META_GROUPS); if (!mg) { dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: DNET_META_GROUPS structure doesn't exist\n", dnet_dump_id_str(ids->id.id)); err = -ENOENT; goto err_out_kcfree; } dnet_convert_meta(mg); if (mg->size % sizeof(int)) { dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: DNET_META_GROUPS structure is corrupted\n", dnet_dump_id_str(ids->id.id)); err = -1; goto err_out_kcfree; } group_num = mg->size / sizeof(int); groups = (int *)mg->data; dnet_convert_meta(mg); } /* Read temporary meta */ temp_mc.data = malloc(sizeof(struct dnet_meta_update) * group_num); if (!temp_mc.data) { err = -ENOMEM; dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: could not allocate memory for temp UPDATE_META\n", dnet_dump_id_str(ids->id.id)); goto err_out_kcfree; } memset(temp_mc.data, 0, sizeof(struct dnet_meta_update) * group_num); temp_mc.size = sizeof(struct dnet_meta_update) * group_num; err = dnet_db_read_raw(p->db->b, &ids->id, (void **)&tmpdata); if (err <= 0) { if (err < 0 && err != -2) goto err_out_free; /* No data in temp meta was stored. Placing local meta_update at the beginning */ mu = temp_mc.data; mu[0].group_id = my_group; mu[0].tm = my_mu.tm; mu[0].flags = my_mu.flags; } else { if (err > (int)(sizeof(struct dnet_meta_update) * group_num)) { dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: too many data stored in temp meta\n", dnet_dump_id_str(ids->id.id)); err = -ENOMEM; goto err_out_free; } memcpy(temp_mc.data, tmpdata, err); } /* Update temp meta with received group */ mu = temp_mc.data; updated = 0; lastest = 0; for (i = 0; i < group_num; ++i) { if (mu[i].group_id == remote_group) { mu[i].tm = ids->last_update.tm; mu[i].flags = ids->last_update.flags; updated = 1; } if (mu[i].group_id == 0) break; if (!(mu[i].flags & DNET_IO_FLAGS_REMOVED)) removed_in_all = 0; if (((mu[i].tm.tsec > mu[lastest].tm.tsec) || ((mu[i].tm.tsec == mu[lastest].tm.tsec) && (mu[i].tm.tnsec > mu[lastest].tm.tnsec))) && i != lastest) { lastest = i; lastest_group = groups[i]; } } if (!updated && i == group_num) { dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: no space left to save group in temp meta!\n", dnet_dump_id_str(ids->id.id)); err = -ENOMEM; goto err_out_free; } if (!updated) { mu[i].group_id = remote_group; mu[i].tm = ids->last_update.tm; mu[i].flags = ids->last_update.flags; if (((mu[i].tm.tsec > mu[lastest].tm.tsec) || ((mu[i].tm.tsec == mu[lastest].tm.tsec) && (mu[i].tm.tnsec > mu[lastest].tm.tnsec))) && i != lastest) { lastest = i; lastest_group = groups[i]; } ++i; } /* Not all groups processed yet */ if (i < group_num) { err = 0; err = dnet_db_write_raw(p->db->b, &ids->id, temp_mc.data, temp_mc.size); if (err) { dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: unable to save temp meta, err: %d\n", dnet_dump_id_str(ids->id.id), err); } goto err_out_free; } /* Check if removal_delay second has gone since object was marked as REMOVED */ if (removed_in_all) { gettimeofday(¤t_ts, NULL); if (((uint64_t)current_ts.tv_sec < mu[lastest].tm.tsec) || ((uint64_t)current_ts.tv_sec - mu[lastest].tm.tsec) < (uint64_t)(state->n->removal_delay * 3600 * 24)) removed_in_all = 0; } /* TODO: receive newer files from remote groups * * Yep, we should read it locally and send it to other groups too */ if ((lastest_group != my_group) && !(mu[lastest].flags & DNET_IO_FLAGS_REMOVED)) { dnet_log(state->n, DNET_LOG_DEBUG, "BULK: %s: File on remote group %d is newer, skipping this file\n", dnet_dump_id_str(ids->id.id), lastest_group); err = 0; goto err_out_free; } for (i = 0; i < group_num; ++i) { err = 0; if (mu[i].group_id == my_group) continue; dnet_session_set_groups(s, (int *)&mu[i].group_id, 1); dnet_setup_id(&id, mu[i].group_id, ids->id.id); id.type = -1; if (mu[lastest].flags & DNET_IO_FLAGS_REMOVED) { if (removed_in_all) { dnet_log(state->n, DNET_LOG_DEBUG, "BULK: dnet_remove_object_now %s in group %d, err=%d\n", dnet_dump_id(&id), mu[i].group_id, err); err = dnet_remove_object_now(s, &id, cflags, ioflags); } else { if (!(mu[i].flags & DNET_IO_FLAGS_REMOVED)) { err = dnet_remove_object(s, &id, NULL, NULL, cflags, ioflags); dnet_log(state->n, DNET_LOG_DEBUG, "BULK: dnet_remove_object %s in group %d err=%d\n", dnet_dump_id(&id), mu[i].group_id, err); } } if (err < 0) goto err_out_cont2; } else { if ((mu[i].tm.tsec < mu[lastest].tm.tsec) || ((mu[i].tm.tsec == mu[lastest].tm.tsec) && ((mu[i].tm.tnsec < mu[lastest].tm.tnsec)))) { err = state->n->cb->send(state, state->n->cb->command_private, &id); if (err) goto err_out_cont2; err = dnet_meta_update_check_status_raw(state->n, &mc); if (err) goto err_out_cont2; memcpy(&mc.id, &id, sizeof(struct dnet_id)); err = dnet_write_metadata(s, &mc, 1, cflags); dnet_log(state->n, DNET_LOG_DEBUG, "BULK: dnet_write_metadata %s in group %d, err=%d\n", dnet_dump_id(&id), my_group, err); if (err < 0) goto err_out_cont2; } } err_out_cont2: if (err < 0) dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: Error during sending transaction to group %d, err=%d\n", dnet_dump_id_str(ids->id.id), groups[i], err); if (!error && err < 0) error = err; } if (mu[lastest].flags & DNET_IO_FLAGS_REMOVED) { if (removed_in_all) { err = dnet_merge_remove_local(state->n, &mc.id, 0); } else if (!(my_mu.flags & DNET_IO_FLAGS_REMOVED)) { err = dnet_merge_remove_local(state->n, &mc.id, 1); } } if (!(mu[lastest].flags & DNET_IO_FLAGS_REMOVED) && !error) { err = dnet_meta_update_check_status(state->n, &mc); if (err) { dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: couldn't update meta CHECK_STATUS\n", dnet_dump_id_str(ids->id.id)); } } if (group_num > 2) { err = dnet_db_remove_raw(p->db->b, &ids->id, 1); if (!err) { dnet_log_raw(state->n, DNET_LOG_ERROR, "BULK: %s: DB: failed to remove temp_meta object, err: %d.\n", dnet_dump_id(&mc.id), err); } } if (error > 0) error = 0; err_out_free: free(temp_mc.data); err_out_kcfree: free(mc.data); if (tmpdata) free(tmpdata); err_out_continue: if (error < 0) { dnet_log(state->n, DNET_LOG_ERROR, "Failed to check ID %s to %s, err=%d\n", dnet_dump_id_str(ids->id.id), dnet_state_dump_addr(state), error); } if (i == group_num) { dnet_counter_inc(state->n, DNET_CNTR_NODE_CHECK_COPY, error); } return error; }
int main(int argc, char *argv[]) { int ch, err, i, have_remote = 0; struct dnet_node *n = NULL; struct dnet_session *s = NULL; struct dnet_config cfg, rem; int max_id_idx = 1000, id_idx = 0; int timeout; unsigned char id[max_id_idx][DNET_ID_SIZE]; char *logfile = "/dev/stderr", *statfile = "/dev/stdout"; FILE *log = NULL, *stat; memset(&cfg, 0, sizeof(struct dnet_config)); cfg.sock_type = SOCK_STREAM; cfg.proto = IPPROTO_TCP; cfg.wait_timeout = 60*60; stat_logger.log_level = DNET_LOG_ERROR; timeout = 1; memcpy(&rem, &cfg, sizeof(struct dnet_config)); while ((ch = getopt(argc, argv, "MFAt:m:w:l:I:r:h")) != -1) { switch (ch) { case 'M': stat_mem = 1; break; case 'F': stat_fs = 1; break; case 'A': stat_la = 1; break; case 't': timeout = atoi(optarg); break; case 'm': stat_logger.log_level = strtoul(optarg, NULL, 0); break; case 'w': cfg.wait_timeout = atoi(optarg); break; case 'L': statfile = optarg; break; case 'l': logfile = optarg; break; case 'I': if (id_idx < max_id_idx) { err = dnet_parse_numeric_id(optarg, id[id_idx]); if (err) return err; id_idx++; } break; case 'r': err = dnet_parse_addr(optarg, &rem); if (err) return err; have_remote = 1; break; case 'h': default: stat_usage(argv[0]); return -1; } } if (!have_remote) { fprintf(stderr, "No remote node specified to route requests.\n"); return -ENOENT; } log = fopen(logfile, "a"); if (!log) { err = -errno; fprintf(stderr, "Failed to open log file %s: %s.\n", logfile, strerror(errno)); return err; } stat_logger.log_private = log; stat_logger.log = dnet_common_log; cfg.log = &stat_logger; stat = fopen(statfile, "a"); if (!stat) { err = -errno; fprintf(stderr, "Failed to open stat file %s: %s.\n", statfile, strerror(errno)); return err; } n = dnet_node_create(&cfg); if (!n) return -1; s = dnet_session_create(n); if (!s) return -1; err = dnet_add_state(n, &rem); if (err) return err; while (1) { struct dnet_id raw; if (!id_idx) { err = dnet_request_stat(s, NULL, DNET_CMD_STAT, 0, stat_complete, stat); if (err < 0) return err; } for (i=0; i<id_idx; ++i) { dnet_setup_id(&raw, 0, id[i]); err = dnet_request_stat(s, &raw, DNET_CMD_STAT, 0, stat_complete, stat); if (err < 0) return err; } sleep(timeout); } return 0; }