redmine

Added dumping support

@@ -17,6 +17,9 @@ @@ -17,6 +17,9 @@
17 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
  20 +#ifndef __CLSYNC_CLSYNC_H
  21 +#define __CLSYNC_CLSYNC_H
  22 +
20 #include <stdio.h> 23 #include <stdio.h>
21 #include <stdint.h> 24 #include <stdint.h>
22 #include <sys/types.h> 25 #include <sys/types.h>
@@ -89,3 +92,5 @@ extern int clsyncapi_getapiversion(); @@ -89,3 +92,5 @@ extern int clsyncapi_getapiversion();
89 */ 92 */
90 extern pid_t clsyncapi_fork(struct ctx *ctx_p); 93 extern pid_t clsyncapi_fork(struct ctx *ctx_p);
91 94
  95 +#endif
  96 +
@@ -182,6 +182,7 @@ typedef struct eventinfo eventinfo_t; @@ -182,6 +182,7 @@ typedef struct eventinfo eventinfo_t;
182 typedef int (*thread_callbackfunct_t)(ctx_t *ctx_p, char **argv); 182 typedef int (*thread_callbackfunct_t)(ctx_t *ctx_p, char **argv);
183 struct threadinfo { 183 struct threadinfo {
184 int thread_num; 184 int thread_num;
  185 + uint32_t iteration;
185 thread_callbackfunct_t callback; 186 thread_callbackfunct_t callback;
186 char **argv; 187 char **argv;
187 pthread_t pthread; 188 pthread_t pthread;
@@ -71,3 +71,5 @@ @@ -71,3 +71,5 @@
71 #define CONFIG_PATHS { ".clsync.conf", "/etc/clsync/clsync.conf", NULL } /* "~/.clsync.conf" and "/etc/clsync/clsync.conf" */ 71 #define CONFIG_PATHS { ".clsync.conf", "/etc/clsync/clsync.conf", NULL } /* "~/.clsync.conf" and "/etc/clsync/clsync.conf" */
72 72
73 #define API_PREFIX "clsyncapi_" 73 #define API_PREFIX "clsyncapi_"
  74 +
  75 +#define DUMP_DIRMODE 0700
@@ -20,7 +20,14 @@ @@ -20,7 +20,14 @@
20 #include "common.h" 20 #include "common.h"
21 21
22 #include <sys/un.h> // for "struct sockaddr_un" 22 #include <sys/un.h> // for "struct sockaddr_un"
  23 +#include <sys/stat.h> // mkdir()
  24 +#include <sys/types.h> // mkdir()
  25 +#include <fcntl.h> // mkdirat()
  26 +#include <glib.h> // g_hash_table_foreach()
23 27
  28 +
  29 +#include "indexes.h"
  30 +#include "ctx.h"
24 #include "error.h" 31 #include "error.h"
25 #include "sync.h" 32 #include "sync.h"
26 #include "control.h" 33 #include "control.h"
@@ -28,19 +35,195 @@ @@ -28,19 +35,195 @@
28 35
29 static pthread_t pthread_control; 36 static pthread_t pthread_control;
30 37
  38 +
  39 +static inline int control_error(clsyncsock_t *clsyncsock_p, const char *const funct, const char *const args) {
  40 + return socket_send(clsyncsock_p, SOCKCMD_REPLY_ECUSTOM, funct, args, errno, strerror(errno));
  41 +}
  42 +
  43 +enum dump_dirfd_obj {
  44 + DUMP_DIRFD_ROOT = 0,
  45 + DUMP_DIRFD_QUEUE,
  46 + DUMP_DIRFD_THREAD,
  47 +
  48 + DUMP_DIRFD_MAX
  49 +};
  50 +
  51 +enum dump_ltype {
  52 + DUMP_LTYPE_INCLUDE,
  53 + DUMP_LTYPE_EXCLUDE,
  54 + DUMP_LTYPE_EVINFO,
  55 +};
  56 +
  57 +struct control_dump_arg {
  58 + clsyncsock_t *clsyncsock_p;
  59 + ctx_t *ctx_p;
  60 + int dirfd[DUMP_DIRFD_MAX];
  61 + int fd_out;
  62 + int data;
  63 +};
  64 +
  65 +void control_dump_liststep(gpointer fpath_gp, gpointer evinfo_gp, gpointer arg_gp) {
  66 + char *fpath = (char *)fpath_gp;
  67 + eventinfo_t *evinfo = (eventinfo_t *)evinfo_gp;
  68 + struct control_dump_arg *arg = arg_gp;
  69 + char act, num;
  70 +
  71 + switch (arg->data) {
  72 + case DUMP_LTYPE_INCLUDE:
  73 + act = '+';
  74 + num = '1';
  75 + break;
  76 + case DUMP_LTYPE_EXCLUDE:
  77 + act = '-';
  78 + num = '1';
  79 + break;
  80 + case DUMP_LTYPE_EVINFO:
  81 + act = '+';
  82 + num = evinfo->flags&EVIF_RECURSIVELY ? '*' :
  83 + (evinfo->flags&EVIF_CONTENTRECURSIVELY ? '/' : '1');
  84 + break;
  85 + default:
  86 + act = '?';
  87 + num = '?';
  88 + }
  89 +
  90 + dprintf(arg->fd_out, "%c%c %s\n", act, num, fpath);
  91 +
  92 + return;
  93 +}
  94 +
  95 +int control_dump_thread(threadinfo_t *threadinfo_p, void *_arg) {
  96 + struct control_dump_arg *arg = _arg;
  97 + char buf[BUFSIZ];
  98 +
  99 + snprintf(buf, BUFSIZ, "%u-%u-%lx", threadinfo_p->iteration, threadinfo_p->thread_num, (long)threadinfo_p->pthread);
  100 +
  101 + arg->fd_out = openat(arg->dirfd[DUMP_DIRFD_THREAD], buf, O_WRONLY);
  102 + if (arg->fd_out == -1)
  103 + return errno;
  104 +
  105 + {
  106 + char **argv;
  107 +
  108 + dprintf(arg->fd_out,
  109 + "thread:\n\titeration == %u;\n\tnum == %u;\n\tpthread == %lx;\n\tstarttime == %lu\n\texpiretime == %lu\n\tchild_pid == %u\n\ttry_n == %u\nCommand:",
  110 + threadinfo_p->iteration,
  111 + threadinfo_p->thread_num,
  112 + (long)threadinfo_p->pthread,
  113 + threadinfo_p->starttime,
  114 + threadinfo_p->expiretime,
  115 + threadinfo_p->child_pid,
  116 + threadinfo_p->try_n
  117 + );
  118 +
  119 + argv = threadinfo_p->argv;
  120 + while (argv != NULL)
  121 + dprintf(arg->fd_out, " \"%s\"", *(argv++));
  122 +
  123 + dprintf(arg->fd_out, "\n");
  124 + }
  125 +
  126 + arg->data = DUMP_LTYPE_EVINFO;
  127 + g_hash_table_foreach(threadinfo_p->fpath2ei_ht, control_dump_liststep, arg);
  128 +
  129 + close(arg->fd_out);
  130 +
  131 + return 0;
  132 +}
  133 +
  134 +int control_mkdir_open(clsyncsock_t *clsyncsock_p, const char *const dir_path) {
  135 + int dirfd;
  136 +
  137 + if (mkdir(dir_path, DUMP_DIRMODE)) {
  138 + control_error(clsyncsock_p, "mkdir", dir_path);
  139 + return -1;
  140 + }
  141 +
  142 + dirfd = open(dir_path, O_RDWR);
  143 + if (dirfd == -1) {
  144 + control_error(clsyncsock_p, "open", dir_path);
  145 + return -1;
  146 + }
  147 +
  148 + return dirfd;
  149 +}
  150 +
  151 +int control_dump(ctx_t *ctx_p, clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p) {
  152 + indexes_t *indexes_p = ctx_p->indexes_p;
  153 + sockcmd_dat_dump_t *dat = sockcmd_p->data;
  154 + int rootfd;
  155 + struct control_dump_arg arg;
  156 + enum dump_dirfd_obj dirfd_obj;
  157 +
  158 + static const char *const subdirs[] = {
  159 + [DUMP_DIRFD_QUEUE] = "queue",
  160 + [DUMP_DIRFD_THREAD] = "threads"
  161 + };
  162 +
  163 + rootfd = control_mkdir_open(clsyncsock_p, dat->dir_path);
  164 + if (rootfd == -1)
  165 + goto l_control_dump_end;
  166 +
  167 + arg.dirfd[DUMP_DIRFD_ROOT] = rootfd;
  168 +
  169 + dirfd_obj = DUMP_DIRFD_ROOT+1;
  170 + while (dirfd_obj < DUMP_DIRFD_MAX) {
  171 + const char *const subdir = subdirs[dirfd_obj];
  172 +
  173 + arg.dirfd[dirfd_obj] = control_mkdir_open(clsyncsock_p, subdir);
  174 + if (arg.dirfd[dirfd_obj] == -1)
  175 + goto l_control_dump_end;
  176 +
  177 + dirfd_obj++;
  178 + }
  179 +
  180 + arg.clsyncsock_p = clsyncsock_p;
  181 + arg.ctx_p = ctx_p;
  182 +
  183 + int queue_id = 0;
  184 + while (queue_id < QUEUE_MAX) {
  185 + char buf[BUFSIZ];
  186 + snprintf(buf, BUFSIZ, "%u", queue_id);
  187 +
  188 + arg.fd_out = openat(arg.dirfd[DUMP_DIRFD_QUEUE], buf, O_WRONLY);
  189 +
  190 + arg.data = DUMP_LTYPE_EVINFO;
  191 + g_hash_table_foreach(indexes_p->fpath2ei_coll_ht[queue_id], control_dump_liststep, &arg);
  192 + arg.data = DUMP_LTYPE_EXCLUDE;
  193 + g_hash_table_foreach(indexes_p->exc_fpath_coll_ht[queue_id], control_dump_liststep, &arg);
  194 +
  195 + close(arg.fd_out);
  196 + queue_id++;
  197 + }
  198 +
  199 + threads_foreach(control_dump_thread, STATE_RUNNING, &arg);
  200 +
  201 +l_control_dump_end:
  202 + dirfd_obj = DUMP_DIRFD_ROOT;
  203 + while (dirfd_obj < DUMP_DIRFD_MAX) {
  204 + if (arg.dirfd[dirfd_obj] != -1)
  205 + close(arg.dirfd[dirfd_obj]);
  206 + dirfd_obj++;
  207 + }
  208 +
  209 + return errno ? errno : socket_send(clsyncsock_p, SOCKCMD_REPLY_DUMP);
  210 +}
  211 +
  212 +
31 int control_procclsyncsock(socket_sockthreaddata_t *arg, sockcmd_t *sockcmd_p) { 213 int control_procclsyncsock(socket_sockthreaddata_t *arg, sockcmd_t *sockcmd_p) {
32 clsyncsock_t *clsyncsock_p = arg->clsyncsock_p; 214 clsyncsock_t *clsyncsock_p = arg->clsyncsock_p;
33 ctx_t *ctx_p = (ctx_t *)arg->arg; 215 ctx_t *ctx_p = (ctx_t *)arg->arg;
34 216
35 switch(sockcmd_p->cmd_id) { 217 switch(sockcmd_p->cmd_id) {
36 - case SOCKCMD_REQUEST_INFO: { 218 + case SOCKCMD_REQUEST_DUMP:
  219 + control_dump(ctx_p, clsyncsock_p, sockcmd_p);
  220 + break;
  221 + case SOCKCMD_REQUEST_INFO:
37 socket_send(clsyncsock_p, SOCKCMD_REPLY_INFO, ctx_p->config_block, ctx_p->label, ctx_p->flags, ctx_p->flags_set); 222 socket_send(clsyncsock_p, SOCKCMD_REPLY_INFO, ctx_p->config_block, ctx_p->label, ctx_p->flags, ctx_p->flags_set);
38 break; 223 break;
39 - } 224 + case SOCKCMD_REQUEST_DIE:
40 - case SOCKCMD_REQUEST_DIE: {  
41 sync_term(SIGTERM); 225 sync_term(SIGTERM);
42 break; 226 break;
43 - }  
44 default: 227 default:
45 return EINVAL; 228 return EINVAL;
46 } 229 }
@@ -232,6 +232,7 @@ struct ctx { @@ -232,6 +232,7 @@ struct ctx {
232 sigset_t *sigset; 232 sigset_t *sigset;
233 char isignoredexitcode[(1<<8)]; 233 char isignoredexitcode[(1<<8)];
234 #endif 234 #endif
  235 + void *indexes_p;
235 }; 236 };
236 typedef struct ctx ctx_t; 237 typedef struct ctx ctx_t;
237 238
@@ -17,6 +17,9 @@ @@ -17,6 +17,9 @@
17 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
  20 +#ifndef __CLSYNC_INDEXES_H
  21 +#define __CLSYNC_INDEXES_H
  22 +
20 #include <glib.h> 23 #include <glib.h>
21 24
22 struct indexes { 25 struct indexes {
@@ -30,3 +33,5 @@ struct indexes { @@ -30,3 +33,5 @@ struct indexes {
30 }; 33 };
31 typedef struct indexes indexes_t; 34 typedef struct indexes indexes_t;
32 35
  36 +#endif
  37 +
@@ -58,6 +58,7 @@ static char *recv_ptrs[SOCKET_MAX]; @@ -58,6 +58,7 @@ static char *recv_ptrs[SOCKET_MAX];
58 58
59 const char *const textmessage_args[SOCKCMD_MAXID] = { 59 const char *const textmessage_args[SOCKCMD_MAXID] = {
60 [SOCKCMD_REQUEST_NEGOTIATION] = "%u", 60 [SOCKCMD_REQUEST_NEGOTIATION] = "%u",
  61 + [SOCKCMD_REQUEST_DUMP] = "%s",
61 [SOCKCMD_REPLY_NEGOTIATION] = "%u", 62 [SOCKCMD_REPLY_NEGOTIATION] = "%u",
62 [SOCKCMD_REPLY_ACK] = "%03u %lu", 63 [SOCKCMD_REPLY_ACK] = "%03u %lu",
63 [SOCKCMD_REPLY_EINVAL] = "%03u %lu", 64 [SOCKCMD_REPLY_EINVAL] = "%03u %lu",
@@ -65,6 +66,9 @@ const char *const textmessage_args[SOCKCMD_MAXID] = { @@ -65,6 +66,9 @@ const char *const textmessage_args[SOCKCMD_MAXID] = {
65 [SOCKCMD_REPLY_INFO] = "%s\003/ %s\003/ %x %x", 66 [SOCKCMD_REPLY_INFO] = "%s\003/ %s\003/ %x %x",
66 [SOCKCMD_REPLY_UNKNOWNCMD] = "%03u %lu", 67 [SOCKCMD_REPLY_UNKNOWNCMD] = "%03u %lu",
67 [SOCKCMD_REPLY_INVALIDCMDID] = "%lu", 68 [SOCKCMD_REPLY_INVALIDCMDID] = "%lu",
  69 + [SOCKCMD_REPLY_EEXIST] = "%s\003/",
  70 + [SOCKCMD_REPLY_EPERM] = "%s\003/",
  71 + [SOCKCMD_REPLY_ECUSTOM] = "%s\003/ %s\003/ %u %s\003/",
68 }; 72 };
69 73
70 const char *const textmessage_descr[SOCKCMD_MAXID] = { 74 const char *const textmessage_descr[SOCKCMD_MAXID] = {
@@ -78,8 +82,12 @@ const char *const textmessage_descr[SOCKCMD_MAXID] = { @@ -78,8 +82,12 @@ const char *const textmessage_descr[SOCKCMD_MAXID] = {
78 [SOCKCMD_REPLY_BYE] = "Bye.", 82 [SOCKCMD_REPLY_BYE] = "Bye.",
79 [SOCKCMD_REPLY_VERSION] = "clsync v%u.%u%s", 83 [SOCKCMD_REPLY_VERSION] = "clsync v%u.%u%s",
80 [SOCKCMD_REPLY_INFO] = "config_block == \"%s\"; label == \"%s\"; flags == %x; flags_set == %x.", 84 [SOCKCMD_REPLY_INFO] = "config_block == \"%s\"; label == \"%s\"; flags == %x; flags_set == %x.",
  85 + [SOCKCMD_REPLY_DUMP] = "Ready",
81 [SOCKCMD_REPLY_UNKNOWNCMD] = "Unknown command.", 86 [SOCKCMD_REPLY_UNKNOWNCMD] = "Unknown command.",
82 [SOCKCMD_REPLY_INVALIDCMDID] = "Invalid command id. Required: 0 <= cmd_id < 1000.", 87 [SOCKCMD_REPLY_INVALIDCMDID] = "Invalid command id. Required: 0 <= cmd_id < 1000.",
  88 + [SOCKCMD_REPLY_EEXIST] = "File exists: \"%s\".",
  89 + [SOCKCMD_REPLY_EPERM] = "Permission denied: \"%s\".",
  90 + [SOCKCMD_REPLY_ECUSTOM] = "%s(%s): Error #%u: \"%s\".",
83 }; 91 };
84 92
85 int socket_check_bysock(int sock) { 93 int socket_check_bysock(int sock) {
@@ -346,6 +354,9 @@ static inline int parse_text_data(sockcmd_t *sockcmd_p, char *args, size_t args_ @@ -346,6 +354,9 @@ static inline int parse_text_data(sockcmd_t *sockcmd_p, char *args, size_t args_
346 case SOCKCMD_REPLY_NEGOTIATION: 354 case SOCKCMD_REPLY_NEGOTIATION:
347 PARSE_TEXT_DATA_SSCANF(sockcmd_dat_negotiation_t, &d->prot, &d->subprot); 355 PARSE_TEXT_DATA_SSCANF(sockcmd_dat_negotiation_t, &d->prot, &d->subprot);
348 break; 356 break;
  357 + case SOCKCMD_REQUEST_DUMP:
  358 + PARSE_TEXT_DATA_SSCANF(sockcmd_dat_dump_t, &d->dir_path);
  359 + break;
349 case SOCKCMD_REPLY_ACK: 360 case SOCKCMD_REPLY_ACK:
350 PARSE_TEXT_DATA_SSCANF(sockcmd_dat_ack_t, &d->cmd_id, &d->cmd_num); 361 PARSE_TEXT_DATA_SSCANF(sockcmd_dat_ack_t, &d->cmd_id, &d->cmd_num);
351 break; 362 break;
@@ -368,10 +379,16 @@ static inline int parse_text_data(sockcmd_t *sockcmd_p, char *args, size_t args_ @@ -368,10 +379,16 @@ static inline int parse_text_data(sockcmd_t *sockcmd_p, char *args, size_t args_
368 case SOCKCMD_REPLY_INVALIDCMDID: 379 case SOCKCMD_REPLY_INVALIDCMDID:
369 PARSE_TEXT_DATA_SSCANF(sockcmd_dat_invalidcmd_t, &d->cmd_num); 380 PARSE_TEXT_DATA_SSCANF(sockcmd_dat_invalidcmd_t, &d->cmd_num);
370 break; 381 break;
  382 + case SOCKCMD_REPLY_EEXIST:
  383 + PARSE_TEXT_DATA_SSCANF(sockcmd_dat_eexist_t, &d->file_path);
  384 + break;
  385 + case SOCKCMD_REPLY_EPERM:
  386 + PARSE_TEXT_DATA_SSCANF(sockcmd_dat_eperm_t, &d->descr);
  387 + break;
371 default: 388 default:
372 sockcmd_p->data = xmalloc(args_len+1); 389 sockcmd_p->data = xmalloc(args_len+1);
373 memcpy(sockcmd_p->data, args, args_len); 390 memcpy(sockcmd_p->data, args, args_len);
374 - sockcmd_p->data[args_len] = 0; 391 + ((char *)sockcmd_p->data)[args_len] = 0;
375 break; 392 break;
376 } 393 }
377 394
@@ -78,18 +78,22 @@ enum sockcmd_id { @@ -78,18 +78,22 @@ enum sockcmd_id {
78 SOCKCMD_REPLY_UNKNOWNCMD = 160, 78 SOCKCMD_REPLY_UNKNOWNCMD = 160,
79 SOCKCMD_REPLY_INVALIDCMDID = 161, 79 SOCKCMD_REPLY_INVALIDCMDID = 161,
80 SOCKCMD_REPLY_EINVAL = 162, 80 SOCKCMD_REPLY_EINVAL = 162,
  81 + SOCKCMD_REPLY_EEXIST = 163,
  82 + SOCKCMD_REPLY_EPERM = 164,
  83 + SOCKCMD_REPLY_ECUSTOM = 199,
81 SOCKCMD_REQUEST_LOGIN = 200, 84 SOCKCMD_REQUEST_LOGIN = 200,
82 SOCKCMD_REQUEST_VERSION = 201, 85 SOCKCMD_REQUEST_VERSION = 201,
83 SOCKCMD_REQUEST_INFO = 202, 86 SOCKCMD_REQUEST_INFO = 202,
  87 + SOCKCMD_REQUEST_DUMP = 203,
84 SOCKCMD_REQUEST_DIE = 210, 88 SOCKCMD_REQUEST_DIE = 210,
85 SOCKCMD_REQUEST_QUIT = 250, 89 SOCKCMD_REQUEST_QUIT = 250,
86 SOCKCMD_REPLY_LOGIN = 300, 90 SOCKCMD_REPLY_LOGIN = 300,
87 SOCKCMD_REPLY_VERSION = 301, 91 SOCKCMD_REPLY_VERSION = 301,
88 SOCKCMD_REPLY_INFO = 302, 92 SOCKCMD_REPLY_INFO = 302,
  93 + SOCKCMD_REPLY_DUMP = 303,
89 SOCKCMD_REPLY_DIE = 310, 94 SOCKCMD_REPLY_DIE = 310,
90 - SOCKCMD_REPLY_UNEXPECTEDEND = 300,  
91 - SOCKCMD_REPLY_QUIT = 301,  
92 SOCKCMD_REPLY_BYE = 350, 95 SOCKCMD_REPLY_BYE = 350,
  96 + SOCKCMD_REPLY_UNEXPECTEDEND = 351,
93 SOCKCMD_MAXID 97 SOCKCMD_MAXID
94 }; 98 };
95 typedef enum sockcmd_id sockcmd_id_t; 99 typedef enum sockcmd_id sockcmd_id_t;
@@ -132,11 +136,26 @@ struct sockcmd_dat_info { @@ -132,11 +136,26 @@ struct sockcmd_dat_info {
132 typedef struct sockcmd_dat_info sockcmd_dat_info_t; 136 typedef struct sockcmd_dat_info sockcmd_dat_info_t;
133 #endif 137 #endif
134 138
  139 +struct sockcmd_dat_dump {
  140 + char dir_path[PATH_MAX];
  141 +};
  142 +typedef struct sockcmd_dat_dump sockcmd_dat_dump_t;
  143 +
  144 +struct sockcmd_dat_eexist {
  145 + char file_path[PATH_MAX];
  146 +};
  147 +typedef struct sockcmd_dat_eexist sockcmd_dat_eexist_t;
  148 +
  149 +struct sockcmd_dat_eperm {
  150 + char descr[BUFSIZ];
  151 +};
  152 +typedef struct sockcmd_dat_eperm sockcmd_dat_eperm_t;
  153 +
135 struct sockcmd { 154 struct sockcmd {
136 uint64_t cmd_num; 155 uint64_t cmd_num;
137 uint16_t cmd_id; 156 uint16_t cmd_id;
138 size_t data_len; 157 size_t data_len;
139 - char *data; 158 + void *data;
140 }; 159 };
141 typedef struct sockcmd sockcmd_t; 160 typedef struct sockcmd sockcmd_t;
142 161
@@ -808,6 +808,7 @@ static inline int so_call_sync(ctx_t *ctx_p, indexes_t *indexes_p, int n, api_ev @@ -808,6 +808,7 @@ static inline int so_call_sync(ctx_t *ctx_p, indexes_t *indexes_p, int n, api_ev
808 threadinfo_p->fpath2ei_ht = g_hash_table_dup(indexes_p->fpath2ei_ht, g_str_hash, g_str_equal, free, free, (gpointer(*)(gpointer))strdup, eidup); 808 threadinfo_p->fpath2ei_ht = g_hash_table_dup(indexes_p->fpath2ei_ht, g_str_hash, g_str_equal, free, free, (gpointer(*)(gpointer))strdup, eidup);
809 threadinfo_p->n = n; 809 threadinfo_p->n = n;
810 threadinfo_p->ei = ei; 810 threadinfo_p->ei = ei;
  811 + threadinfo_p->iteration = ctx_p->iteration_num;
811 812
812 if (ctx_p->synctimeout) 813 if (ctx_p->synctimeout)
813 threadinfo_p->expiretime = threadinfo_p->starttime + ctx_p->synctimeout; 814 threadinfo_p->expiretime = threadinfo_p->starttime + ctx_p->synctimeout;
@@ -940,6 +941,7 @@ static inline int so_call_rsync(ctx_t *ctx_p, indexes_t *indexes_p, const char * @@ -940,6 +941,7 @@ static inline int so_call_rsync(ctx_t *ctx_p, indexes_t *indexes_p, const char *
940 threadinfo_p->ctx_p = ctx_p; 941 threadinfo_p->ctx_p = ctx_p;
941 threadinfo_p->starttime = time(NULL); 942 threadinfo_p->starttime = time(NULL);
942 threadinfo_p->fpath2ei_ht = g_hash_table_dup(indexes_p->fpath2ei_ht, g_str_hash, g_str_equal, free, free, (gpointer(*)(gpointer))strdup, eidup); 943 threadinfo_p->fpath2ei_ht = g_hash_table_dup(indexes_p->fpath2ei_ht, g_str_hash, g_str_equal, free, free, (gpointer(*)(gpointer))strdup, eidup);
  944 + threadinfo_p->iteration = ctx_p->iteration_num;
943 945
944 threadinfo_p->argv[0] = strdup(inclistfile); 946 threadinfo_p->argv[0] = strdup(inclistfile);
945 threadinfo_p->argv[1] = strdup(exclistfile); 947 threadinfo_p->argv[1] = strdup(exclistfile);
@@ -1187,6 +1189,7 @@ static inline int sync_exec_thread(ctx_t *ctx_p, indexes_t *indexes_p, thread_ca @@ -1187,6 +1189,7 @@ static inline int sync_exec_thread(ctx_t *ctx_p, indexes_t *indexes_p, thread_ca
1187 threadinfo_p->ctx_p = ctx_p; 1189 threadinfo_p->ctx_p = ctx_p;
1188 threadinfo_p->starttime = time(NULL); 1190 threadinfo_p->starttime = time(NULL);
1189 threadinfo_p->fpath2ei_ht = g_hash_table_dup(indexes_p->fpath2ei_ht, g_str_hash, g_str_equal, free, free, (gpointer(*)(gpointer))strdup, eidup); 1191 threadinfo_p->fpath2ei_ht = g_hash_table_dup(indexes_p->fpath2ei_ht, g_str_hash, g_str_equal, free, free, (gpointer(*)(gpointer))strdup, eidup);
  1192 + threadinfo_p->iteration = ctx_p->iteration_num;
1190 1193
1191 if (ctx_p->synctimeout) 1194 if (ctx_p->synctimeout)
1192 threadinfo_p->expiretime = threadinfo_p->starttime + ctx_p->synctimeout; 1195 threadinfo_p->expiretime = threadinfo_p->starttime + ctx_p->synctimeout;
@@ -2678,14 +2681,14 @@ int sync_idle_dosync_collectedevents(ctx_t *ctx_p, indexes_t *indexes_p) { @@ -2678,14 +2681,14 @@ int sync_idle_dosync_collectedevents(ctx_t *ctx_p, indexes_t *indexes_p) {
2678 g_hash_table_remove_all(indexes_p->fpath2ei_ht); 2681 g_hash_table_remove_all(indexes_p->fpath2ei_ht);
2679 } 2682 }
2680 2683
2681 - if (!ctx_p->flags[THREADING]) {  
2682 if(ctx_p->iteration_num < ~0) // ~0 is the max value for unsigned variables 2684 if(ctx_p->iteration_num < ~0) // ~0 is the max value for unsigned variables
2683 ctx_p->iteration_num++; 2685 ctx_p->iteration_num++;
  2686 +
  2687 + if (!ctx_p->flags[THREADING])
2684 setenv_iteration(ctx_p->iteration_num); 2688 setenv_iteration(ctx_p->iteration_num);
2685 2689
2686 debug(3, "next iteration: %u/%u", 2690 debug(3, "next iteration: %u/%u",
2687 ctx_p->iteration_num, ctx_p->flags[MAXITERATIONS]); 2691 ctx_p->iteration_num, ctx_p->flags[MAXITERATIONS]);
2688 - }  
2689 2692
2690 return 0; 2693 return 0;
2691 } 2694 }
@@ -3326,6 +3329,8 @@ int sync_run(ctx_t *ctx_p) { @@ -3326,6 +3329,8 @@ int sync_run(ctx_t *ctx_p) {
3326 // Creating hash tables 3329 // Creating hash tables
3327 3330
3328 indexes_t indexes = {NULL}; 3331 indexes_t indexes = {NULL};
  3332 + ctx_p->indexes_p = &indexes;
  3333 +
3329 indexes.wd2fpath_ht = g_hash_table_new_full(g_direct_hash, g_direct_equal, 0, 0); 3334 indexes.wd2fpath_ht = g_hash_table_new_full(g_direct_hash, g_direct_equal, 0, 0);
3330 indexes.fpath2wd_ht = g_hash_table_new_full(g_str_hash, g_str_equal, free, 0); 3335 indexes.fpath2wd_ht = g_hash_table_new_full(g_str_hash, g_str_equal, free, 0);
3331 indexes.fpath2ei_ht = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); 3336 indexes.fpath2ei_ht = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
@@ -19,4 +19,5 @@ @@ -19,4 +19,5 @@
19 19
20 extern int sync_run(struct ctx *ctx); 20 extern int sync_run(struct ctx *ctx);
21 extern int sync_term(int exitcode); 21 extern int sync_term(int exitcode);
  22 +extern int threads_foreach(int (*funct)(threadinfo_t *, void *), state_t state, void *arg);
22 23