static fqd_queue_impl_data queue_jlog_setup(fq_rk *qname, uint32_t *count) { char qpath[PATH_MAX]; jlog_id chkpt; struct queue_jlog *d; d = calloc(1, sizeof(*d)); d->auto_chkpt = true; fqd_config_construct_queue_path(qpath, sizeof(qpath), qname); d->qpath = strdup(qpath); d->writer = jlog_new(d->qpath); if(jlog_ctx_open_writer(d->writer) != 0) { jlog_ctx_close(d->writer); d->writer = jlog_new(d->qpath); if(jlog_ctx_init(d->writer) != 0) { fq_debug(FQ_DEBUG_IO, "jlog init: %s\n", jlog_ctx_err_string(d->writer)); goto bail; } jlog_ctx_close(d->writer); d->writer = jlog_new(d->qpath); if(jlog_ctx_open_writer(d->writer) != 0) { fq_debug(FQ_DEBUG_IO, "jlog writer: %s\n", jlog_ctx_err_string(d->writer)); goto bail; } } d->reader = jlog_new(d->qpath); if(jlog_get_checkpoint(d->reader, "fq", &chkpt) != 0) { if(jlog_ctx_add_subscriber(d->reader, "fq", JLOG_BEGIN) != 0) { fq_debug(FQ_DEBUG_IO, "jlog add sub: %s\n", jlog_ctx_err_string(d->reader)); goto bail; } } if(jlog_ctx_open_reader(d->reader, "fq") != 0) { fq_debug(FQ_DEBUG_IO, "jlog: %s\n", jlog_ctx_err_string(d->reader)); goto bail; } uuid_generate(d->uuid); write_sig(d); *count = 0; (void)qname; return d; bail: if(d->writer) jlog_ctx_close(d->writer); if(d->reader) jlog_ctx_close(d->reader); free(d->qpath); free(d); return NULL; }
void jcreate(jlog_safety s) { jlog_ctx *ctx; const char *label = NULL; switch (s) { case JLOG_ALMOST_SAFE: label = "almost safe"; break; case JLOG_UNSAFE: label = "unsafe"; break; case JLOG_SAFE: label = "safe"; break; } fprintf(stderr, "jcreate %s in %s mode\n", LOGNAME, label); ctx = jlog_new(LOGNAME); jlog_ctx_alter_journal_size(ctx, 102400); jlog_ctx_alter_safety(ctx, s); if(jlog_ctx_init(ctx) != 0) { fprintf(stderr, "jlog_ctx_init failed: %d %s\n", jlog_ctx_err(ctx), jlog_ctx_err_string(ctx)); if(jlog_ctx_err(ctx) != JLOG_ERR_CREATE_EXISTS) exit(0); } else { jlog_ctx_add_subscriber(ctx, MASTER, JLOG_BEGIN); } jlog_ctx_close(ctx); }
static int jlog_logio_open(noit_log_stream_t ls) { char path[PATH_MAX], *sub, **subs, *p; jlog_asynch_ctx *actx; jlog_ctx *log = NULL; pthread_attr_t tattr; int i, listed, found; if(jlog_lspath_to_fspath(ls, path, sizeof(path), &sub) <= 0) return -1; log = jlog_new(path); if(!log) return -1; jlog_set_error_func(log, noit_log_jlog_err, ls); /* Open the writer. */ if(jlog_ctx_open_writer(log)) { /* If that fails, we'll give one attempt at initiailizing it. */ /* But, since we attempted to open it as a writer, it is tainted. */ /* path: close, new, init, close, new, writer, add subscriber */ jlog_ctx_close(log); log = jlog_new(path); jlog_set_error_func(log, noit_log_jlog_err, ls); if(jlog_ctx_init(log)) { noitL(noit_error, "Cannot init jlog writer: %s\n", jlog_ctx_err_string(log)); jlog_ctx_close(log); return -1; } /* After it is initialized, we can try to reopen it as a writer. */ jlog_ctx_close(log); log = jlog_new(path); jlog_set_error_func(log, noit_log_jlog_err, ls); if(jlog_ctx_open_writer(log)) { noitL(noit_error, "Cannot open jlog writer: %s\n", jlog_ctx_err_string(log)); jlog_ctx_close(log); return -1; } } /* Add or remove subscribers according to the current configuration. */ listed = jlog_ctx_list_subscribers(log, &subs); if(listed == -1) { noitL(noit_error, "Cannot list jlog subscribers: %s\n", jlog_ctx_err_string(log)); return -1; } if(sub) { /* Match all configured subscribers against jlog's list. */ for(p=strtok(sub, ",");p;p=strtok(NULL, ",")) { for(i=0;i<listed;i++) { if((subs[i]) && (strcmp(p, subs[i]) == 0)) { free(subs[i]); subs[i] = NULL; break; } } if(i == listed) jlog_ctx_add_subscriber(log, p, JLOG_BEGIN); } /* Remove all unmatched subscribers. */ for(i=0;i<listed;i++) { if(subs[i]) { jlog_ctx_remove_subscriber(log, subs[i]); free(subs[i]); subs[i] = NULL; } } free(subs); subs = NULL; } else { /* Remove all subscribers other than DEFAULT_JLOG_SUBSCRIBER. */ found = 0; for(i=0;i<listed;i++) { if((subs[i]) && (strcmp(DEFAULT_JLOG_SUBSCRIBER, subs[i]) == 0)) { found = 1; continue; } jlog_ctx_remove_subscriber(log, subs[i]); } /* Add DEFAULT_JLOG_SUBSCRIBER if it wasn't already on the jlog's list. */ if(!found) jlog_ctx_add_subscriber(log, DEFAULT_JLOG_SUBSCRIBER, JLOG_BEGIN); jlog_ctx_list_subscribers_dispose(log, subs); } actx = calloc(1, sizeof(*actx)); actx->log = log; ls->op_ctx = actx; pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if(pthread_create(&actx->writer, NULL, jlog_logio_asynch_writer, ls) != 0) return -1; /* We do this to clean things up */ jlog_logio_reopen(ls); return 0; }
/* * returns -1 when the incoming checkpoint is out of range of the log * returns -2 if there was an error actually setting the checkpoint */ static int queue_log_add_checkpoint(fqd_queue_impl_data data, const char *name, const fq_msgid *id) { struct queue_jlog *d = (struct queue_jlog *)data; jlog_id jid = { .log = id->id.u32.p1, .marker = id->id.u32.p2 }; /* ensure the checkpoint makes sense */ jlog_id first = { .log = 0, .marker = 0 }; jlog_id last = { .log = 0, .marker = 0 }; jlog_ctx_first_log_id(d->reader, &first); jlog_ctx_last_log_id(d->reader, &last); if (! (jid.log >= first.log && jid.log <= last.log && jid.marker >= first.marker && jid.marker <= last.marker)) { return -1; } char **subs; int sub_count = jlog_ctx_list_subscribers(d->reader, &subs); int have_it = 0; for (int i = 0; i < sub_count; i++) { have_it += strcmp(subs[i], name) == 0 ? 1 : 0; } if (have_it == 0) { jlog_ctx_add_subscriber(d->reader, name, JLOG_BEGIN); } if (jlog_ctx_read_checkpoint(d->reader, &jid) == -1) { /* If we failed to checkpoint we are in a situation where the 'add_subscriber' call above put them at the beginning of the log so we have to remove the subscriber if we just added them However, if they already existed and had a previous good checkpoint, leave it alone */ if (have_it == 0) { jlog_ctx_remove_subscriber(d->reader, name); } return -2; } return 0; } /* * return -1 if the subscriber doesn't exist * return 0 on success */ static int queue_log_remove_checkpoint(fqd_queue_impl_data data, const char *name) { struct queue_jlog *d = (struct queue_jlog *)data; if (jlog_ctx_remove_subscriber(d->reader, name) == 0) { return -1; } return 0; } /* * return -1 if the subscriber doesn't exist * return -2 if we can't reset the checkpoint * return 0 on success */ static int queue_log_reset_to_checkpoint(fqd_queue_impl_data data, const char *name) { struct queue_jlog *d = (struct queue_jlog *)data; char **subs; int sub_count = jlog_ctx_list_subscribers(d->reader, &subs); int have_it = 0; for (int i = 0; i < sub_count; i++) { have_it += strcmp(subs[i], name) == 0 ? 1 : 0; } if (have_it == 0) { return -1; } jlog_id checkpoint; if (jlog_get_checkpoint(d->reader, name, &checkpoint) == -1) { return -2; } if (jlog_ctx_read_checkpoint(d->reader, &checkpoint) == -1) { return -2; } return 0; } static int write_sig(struct queue_jlog *d) { char sigfile[PATH_MAX]; int fd; snprintf(sigfile, sizeof(sigfile), "%s/.sig", d->qpath); fd = open(sigfile, O_CREAT|O_TRUNC|O_WRONLY, 0640); if(fd < 0) return -1; write(fd, d->uuid, 16); close(fd); return 0; } static int read_sig(struct queue_jlog *d, uuid_t out) { char sigfile[PATH_MAX]; int fd, rv; snprintf(sigfile, sizeof(sigfile), "%s/.sig", d->qpath); fd = open(sigfile, O_RDONLY); if(fd < 0) return -1; rv = read(fd, out, 16); close(fd); return (rv == 16) ? 0 : -1; } static fqd_queue_impl_data queue_jlog_setup(fq_rk *qname, uint32_t *count) { char qpath[PATH_MAX]; jlog_id chkpt; struct queue_jlog *d; d = calloc(1, sizeof(*d)); d->auto_chkpt = true; fqd_config_construct_queue_path(qpath, sizeof(qpath), qname); d->qpath = strdup(qpath); d->writer = jlog_new(d->qpath); jlog_ctx_set_pre_commit_buffer_size(d->writer, 1024 * 1024); jlog_ctx_set_multi_process(d->writer, 0); jlog_ctx_set_use_compression(d->writer, 1); if(jlog_ctx_open_writer(d->writer) != 0) { jlog_ctx_close(d->writer); d->writer = jlog_new(d->qpath); jlog_ctx_set_pre_commit_buffer_size(d->writer, 1024 * 1024); jlog_ctx_set_multi_process(d->writer, 0); jlog_ctx_set_use_compression(d->writer, 1); if(jlog_ctx_init(d->writer) != 0) { fq_debug(FQ_DEBUG_IO, "jlog init: %s\n", jlog_ctx_err_string(d->writer)); goto bail; } jlog_ctx_close(d->writer); d->writer = jlog_new(d->qpath); jlog_ctx_set_pre_commit_buffer_size(d->writer, 1024 * 1024); jlog_ctx_set_multi_process(d->writer, 0); jlog_ctx_set_use_compression(d->writer, 1); if(jlog_ctx_open_writer(d->writer) != 0) { fq_debug(FQ_DEBUG_IO, "jlog writer: %s\n", jlog_ctx_err_string(d->writer)); goto bail; } } /* 128MB journal chunks */ jlog_ctx_alter_journal_size(d->writer, 128 * 1024 * 1024); d->reader = jlog_new(d->qpath); if(jlog_get_checkpoint(d->reader, "fq", &chkpt) != 0) { if(jlog_ctx_add_subscriber(d->reader, "fq", JLOG_BEGIN) != 0) { fq_debug(FQ_DEBUG_IO, "jlog add sub: %s\n", jlog_ctx_err_string(d->reader)); goto bail; } } if(jlog_ctx_open_reader(d->reader, "fq") != 0) { fq_debug(FQ_DEBUG_IO, "jlog: %s\n", jlog_ctx_err_string(d->reader)); goto bail; } uuid_generate(d->uuid); write_sig(d); *count = d->count = jlog_ctx_read_interval(d->reader, &d->start, &d->finish); (void)qname; return d; bail: if(d->writer) jlog_ctx_close(d->writer); if(d->reader) jlog_ctx_close(d->reader); free(d->qpath); free(d); return NULL; }