Populate cache on READ command when DNET_IO_FLAGS_CACHE ioflag is set
[elliptics.git] / library / check_common.c
blob1dc301fd143705932f249055e969722b1746c284
1 /*
2 * 2008+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/mman.h>
20 #include <dirent.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
28 #include "elliptics.h"
29 #include "elliptics/interface.h"
31 static int dnet_check_complete(struct dnet_net_state *state, struct dnet_cmd *cmd, void *priv)
33 struct dnet_wait *w = priv;
34 int err = -EINVAL;
36 if (is_trans_destroyed(state, cmd)) {
37 dnet_wakeup(w, w->cond++);
38 dnet_wait_put(w);
39 return 0;
42 if (cmd->size == sizeof(struct dnet_check_reply)) {
43 struct dnet_check_reply *r = (struct dnet_check_reply *)(cmd + 1);
45 dnet_convert_check_reply(r);
47 dnet_log(state->n, DNET_LOG_INFO, "check: total: %d, completed: %d, errors: %d\n",
48 r->total, r->completed, r->errors);
51 w->status = cmd->status;
52 return err;
55 static int dnet_send_check_request(struct dnet_net_state *st, struct dnet_id *id,
56 struct dnet_wait *w, struct dnet_check_request *r)
58 struct dnet_trans_control ctl;
59 char ctl_time[64];
60 struct tm tm;
62 memset(&ctl, 0, sizeof(struct dnet_trans_control));
64 memcpy(&ctl.id, id, sizeof(struct dnet_id));
65 ctl.cmd = DNET_CMD_LIST;
66 ctl.complete = dnet_check_complete;
67 ctl.priv = w;
68 ctl.cflags = DNET_FLAGS_NEED_ACK | DNET_FLAGS_NOLOCK;
70 if (r->timestamp) {
71 localtime_r((time_t *)&r->timestamp, &tm);
72 strftime(ctl_time, sizeof(ctl_time), "%F %R:%S %Z", &tm);
73 } else {
74 snprintf(ctl_time, sizeof(ctl_time), "all records");
77 dnet_log(st->n, DNET_LOG_INFO, "%s: check request: objects: %llu, threads: %llu, timestamp: %s, merge: %d\n",
78 dnet_state_dump_addr(st), (unsigned long long)r->obj_num, (unsigned long long)r->thread_num,
79 ctl_time, !!(r->flags & DNET_CHECK_MERGE));
81 dnet_convert_check_request(r);
83 ctl.data = r;
84 ctl.size = sizeof(*r) + r->obj_num * sizeof(struct dnet_id) + r->group_num * sizeof(int);
86 return dnet_trans_alloc_send_state(st, &ctl);
89 int dnet_request_check(struct dnet_node *n, struct dnet_check_request *r)
91 struct dnet_wait *w;
92 struct dnet_net_state *st;
93 struct dnet_group *g;
94 int err, num = 0;
96 w = dnet_wait_alloc(0);
97 if (!w) {
98 err = -ENOMEM;
99 goto err_out_exit;
102 pthread_mutex_lock(&n->state_lock);
103 list_for_each_entry(g, &n->group_list, group_entry) {
104 list_for_each_entry(st, &g->state_list, state_entry) {
105 struct dnet_id raw;
107 if (st == n->st)
108 continue;
110 dnet_wait_get(w);
112 dnet_setup_id(&raw, st->idc->group->group_id, st->idc->ids[0].raw.id);
113 dnet_send_check_request(st, &raw, w, r);
114 num++;
117 pthread_mutex_unlock(&n->state_lock);
119 err = dnet_wait_event(w, w->cond == num, &n->wait_ts);
120 if (err)
121 goto err_out_put;
123 if (w->status) {
124 err = w->status;
125 goto err_out_put;
128 dnet_wait_put(w);
130 return num;
132 err_out_put:
133 dnet_wait_put(w);
134 err_out_exit:
135 dnet_log(n, DNET_LOG_ERROR, "Check exited with status %d\n", err);
136 return err;