static void locking_slave(int in_fd, int out_fd) { char cmd; int rv; file_lock *lock = file_lock_new(TEST_FILENAME); gboolean locked = 0; while (1) { if (!pipeget(in_fd, &cmd)) cmd = 'q'; switch (cmd) { case 'q': /* q = quit */ tu_dbg("slave: quitting\n"); file_lock_free(lock); lock = NULL; return; case 'l': /* l = try locking; reply with 'y' or 'n' */ g_assert(!locked); rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return; } tu_dbg("slave: lock attempt => %s\n", (rv == 1)? "n" : "y"); pipeput(out_fd, (rv == 1)? "n" : "y"); if (rv != 1) locked = 1; break; case 'i': /* i = increment counter, reply with new value */ g_assert(locked); if (!inc_counter(lock)) return; tu_dbg("slave: inc'd to %c\n", lock->data[0]); pipeput(out_fd, lock->data); break; case 'u': /* u = try unlocking; reply with 'k' */ g_assert(locked); rv = file_lock_unlock(lock); if (rv != 0) { g_fprintf(stderr, "file_lock_unlock: %s\n", strerror(errno)); return; } tu_dbg("slave: unlocked\n"); pipeput(out_fd, "k"); locked = 0; break; default: return; } } }
cmddatas_t * read_cmdfile( char *filename) { cmddatas_t *cmddatas = g_new0(cmddatas_t, 1); char **xlines; int i; pid_t pids[NB_PIDS]; pid_t new_pids[NB_PIDS]; int nb_pids = 0; int result; gboolean generic_command_restore = FALSE; gboolean specific_command_restore = FALSE; cmddatas->lock = file_lock_new(filename); cmddatas->cmdfile = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, &free_cmddata); need_rewrite = FALSE; // open while ((result = file_lock_lock(cmddatas->lock)) == 1) { sleep(1); } if (result != 0) { g_debug("read_cmdfile open failed: %s", strerror(errno)); } if (!cmddatas->lock->data) { cmddatas->version = 1; cmddatas->max_id = 0; return cmddatas; } xlines = g_strsplit(cmddatas->lock->data, "\n", 0); // read if (sscanf(xlines[0], "VERSION %d", &cmddatas->version) != 1) {}; if (sscanf(xlines[1], "ID %d", &cmddatas->max_id) != 1) {}; // read cmd for (i=2; xlines[i] != NULL; i++) { cmddata_t *cmddata = cmdfile_parse_line(xlines[i], &generic_command_restore, &specific_command_restore); if (!cmddata) continue; /* validate working_pid */ if (!checked_working_pid && cmddata->working_pid != 0) { int i; for (i = 0; i < nb_pids; i++) { if (pids[i] == cmddata->working_pid) { cmddata->working_pid = new_pids[i]; i += 100; continue; } } if (nb_pids < NB_PIDS) { pids[nb_pids] = cmddata->working_pid; if (kill(cmddata->working_pid, 0) != 0) cmddata->working_pid =0; new_pids[nb_pids] = cmddata->working_pid; nb_pids++; } } g_hash_table_insert(cmddatas->cmdfile, GINT_TO_POINTER(cmddata->id), cmddata); } if (generic_command_restore) { if (specific_command_restore) { /* set expire to NOW+24h of all genric command_restore */ g_hash_table_foreach(cmddatas->cmdfile, &cmdfile_set_expire, NULL); } else { /* check start_time of all generic command_restore and remove them */ g_hash_table_foreach(cmddatas->cmdfile, &cmdfile_set_to_DONE, NULL); } } g_strfreev(xlines); checked_working_pid = 1; if (need_rewrite) { write_cmdfile(cmddatas); return read_cmdfile(filename); } return cmddatas; }
static int locking_master(int in_fd, int out_fd) { file_lock *lock = file_lock_new(TEST_FILENAME); int rv; char slaveres; /* start by locking here and incrementing the value */ rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return 0; } g_assert(rv != 1); /* not already locked */ tu_dbg("master: locked\n"); if (!inc_counter(lock)) return 0; g_assert(lock->data[0] == 'b'); tu_dbg("master: inc'd to b\n"); /* unlock and re-lock */ rv = file_lock_unlock(lock); if (rv != 0) { g_fprintf(stderr, "file_lock_unlock: %s\n", strerror(errno)); return 0; } tu_dbg("master: unlocked\n"); rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return 0; } g_assert(rv != 1); /* not already locked */ tu_dbg("master: locked\n"); /* inc it again */ g_assert(lock->data[0] == 'b'); inc_counter(lock); g_assert(lock->data[0] == 'c'); tu_dbg("master: inc'd to c\n"); /* the slave should fail to get a lock now */ pipeput(out_fd, "l"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'n'); /* and, finally unlock */ rv = file_lock_unlock(lock); if (rv != 0) { g_fprintf(stderr, "file_lock_unlock: %s\n", strerror(errno)); return 0; } tu_dbg("master: unlocked\n"); /* the slave should succeed now */ pipeput(out_fd, "l"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'y'); pipeput(out_fd, "i"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'd'); /* master shouldn't be able to lock now */ rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return 0; } g_assert(rv == 1); /* already locked */ tu_dbg("master: lock attempt failed (as expected)\n"); pipeput(out_fd, "i"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'e'); /* get the slave to unlock */ pipeput(out_fd, "u"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'k'); /* we should get a lock now */ rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return 0; } g_assert(rv != 1); /* not already locked */ tu_dbg("master: lock attempt succeeded\n"); g_assert(lock->data[0] == 'e'); /* leave it unlocked, just to see what happens */ return 1; }
cmddatas_t * read_cmdfile( char *filename) { cmddatas_t *cmddatas = g_new0(cmddatas_t, 1); cmddata_t *cmddata; char *s, *fp, *operation; char ch; char **xlines; int i; int pid; pid_t pids[NB_PIDS]; pid_t new_pids[NB_PIDS]; int nb_pids = 0; int result; gboolean generic_command_restore = FALSE; gboolean specific_command_restore = FALSE; cmddatas->lock = file_lock_new(filename); cmddatas->cmdfile = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, &free_cmddata); need_rewrite = FALSE; // open while ((result = file_lock_lock(cmddatas->lock)) == 1) { sleep(1); } if (result != 0) { g_debug("read_cmdfile open failed: %s", strerror(errno)); } if (!cmddatas->lock->data) { cmddatas->version = 1; cmddatas->max_id = 0; return cmddatas; } xlines = g_strsplit(cmddatas->lock->data, "\n", 0); // read if (sscanf(xlines[0], "VERSION %d", &cmddatas->version) != 1) {}; if (sscanf(xlines[1], "ID %d", &cmddatas->max_id) != 1) {}; // read cmd for (i=2; xlines[i] != NULL; i++) { int id; s = xlines[i]; if (*s == '\0') continue; ch = *s++; skip_whitespace(s, ch); if (ch == '\0' || sscanf((s - 1), "%d", &id) != 1) { continue; } skip_integer(s, ch); skip_whitespace(s, ch); operation = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (!g_str_equal(operation, "FLUSH") && !g_str_equal(operation, "COPY") && !g_str_equal(operation, "RESTORE")) { g_debug("BAD operation %s: %s", operation, s); continue; } cmddata = g_new0(cmddata_t, 1); cmddata->id = id; skip_whitespace(s, ch); fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; cmddata->config = unquote_string(fp); if (g_str_equal(operation, "FLUSH")) { cmddata->operation = CMD_FLUSH; skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->holding_file = unquote_string(fp); } else if (g_str_equal(operation, "COPY")) { char *src_labels; char *slabels; char *a; cmddata->operation = CMD_COPY; skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_storage = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_pool = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_label = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->src_fileno = atoi(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; slabels = src_labels = unquote_string(fp); cmddata->src_labels_str = g_strdup(src_labels); a = strstr(slabels, " ;"); if (a) { slabels = a+2; while ((a = strstr(slabels, " ;"))) { *a = '\0'; cmddata->src_labels = g_slist_append(cmddata->src_labels, g_strdup(slabels)); slabels = a+2; } } g_free(src_labels); skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->start_time = atoll(fp); } else if (g_str_equal(operation, "RESTORE")) { cmddata->operation = CMD_RESTORE; skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_storage = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->src_pool = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; if (g_str_equal(cmddata->src_pool, "HOLDING")) { cmddata->holding_file = unquote_string(fp); } else { cmddata->src_label = unquote_string(fp); } skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->src_fileno = atoi(fp); skip_whitespace(s,ch); fp = s - 1; skip_integer(s, ch); s[-1] = '\0'; cmddata->expire = atoll(fp); } else { } skip_whitespace(s, ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->hostname = unquote_string(fp); skip_whitespace(s, ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->diskname = unquote_string(fp); skip_whitespace(s, ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->dump_timestamp = unquote_string(fp); skip_whitespace(s,ch); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->level = atoi(fp); skip_whitespace(s, ch); if (cmddata->operation != CMD_RESTORE) { fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; cmddata->dst_storage = unquote_string(fp); skip_whitespace(s, ch); } fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (sscanf(fp, "WORKING:%d", &pid) != 1) { } cmddata->working_pid = pid; if (cmddata->operation == CMD_RESTORE) { if (cmddata->working_pid == 0) generic_command_restore = TRUE; else specific_command_restore = TRUE; } skip_whitespace(s, ch); fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (g_str_equal(fp, "DONE")) { cmddata->status = CMD_DONE; } else if (g_str_equal(fp, "TODO")) { cmddata->status = CMD_TODO; } else if (strncmp(fp, "PARTIAL", 7) == 0) { long long lsize; cmddata->status = CMD_PARTIAL; if (sscanf(fp, "PARTIAL:%lld", &lsize) != 1) { } else { cmddata->size = lsize; } } else { } /* validate working_pid */ if (!checked_working_pid && cmddata->working_pid != 0) { int i; for (i = 0; i < nb_pids; i++) { if (pids[i] == cmddata->working_pid) { cmddata->working_pid = new_pids[i]; i += 100; continue; } } if (nb_pids < NB_PIDS) { pids[nb_pids] = cmddata->working_pid; if (kill(cmddata->working_pid, 0) != 0) cmddata->working_pid =0; new_pids[nb_pids] = cmddata->working_pid; nb_pids++; } } g_hash_table_insert(cmddatas->cmdfile, GINT_TO_POINTER(cmddata->id), cmddata); } if (generic_command_restore) { if (specific_command_restore) { /* set expire to NOW+24h of all genric command_restore */ g_hash_table_foreach(cmddatas->cmdfile, &cmdfile_set_expire, NULL); } else { /* check start_time of all generic command_restore and remove them */ g_hash_table_foreach(cmddatas->cmdfile, &cmdfile_set_to_DONE, NULL); } } g_strfreev(xlines); checked_working_pid = 1; if (need_rewrite) { write_cmdfile(cmddatas); return read_cmdfile(filename); } return cmddatas; }