/* This may be too slow because the tree could end up very unbalanced if presented in alphabetical order. Probably better to switch to C++ and use STL. Or could hash the strings first. Or use a balancing data structure. */ TREE_T *tree_get(TREE_T *t,char *name) { int x=strcmp(name,t->s); if (x==0) return t; if (x<0) { if (!t->lt) t->lt=tree_new(name); return tree_get(t->lt,name); } if (!t->gt) t->gt=tree_new(name); return tree_get(t->gt,name); }
static int queue_ram_envelope_update(uint64_t evpid, const char *buf, size_t len) { struct qr_envelope *evp; struct qr_message *msg; void *tmp; if ((msg = get_message(evpid_to_msgid(evpid))) == NULL) return (0); if ((evp = tree_get(&msg->envelopes, evpid)) == NULL) { log_warn("warn: queue-ram: not found"); return (0); } tmp = malloc(len); if (tmp == NULL) { log_warn("warn: queue-ram: malloc"); return (0); } memmove(tmp, buf, len); free(evp->buf); evp->len = len; evp->buf = tmp; stat_decrement("queue.ram.envelope.size", evp->len); stat_increment("queue.ram.envelope.size", len); return (1); }
int ydb_get(YDB ydb, char *key, unsigned short key_sz, char *buf, int buf_sz) { struct db *db = (struct db *) ydb; assert(db->magic == YDB_STRUCT_MAGIC); DB_LOCK(db); struct item *item = tree_get(db->tree, key, key_sz); if(item == NULL) goto error; int needed = item->value_sz + MAX_PADDING + sizeof(struct ydb_value_record); if(buf_sz < needed) { log_error("ydb_get:buffer too small. is %i, should be at least %i", buf_sz, needed); goto error; } int r = loglist_get(db->loglist, item->logno, item->value_offset, item->value_sz, buf, buf_sz); if(r < 0) goto error; DB_UNLOCK(db); return(r); error: DB_UNLOCK(db); return(-1); }
/* Write all entries in t into the backup tree and free storage*/ void tree_commit(TREE_T *backup,TREE_T *t) { if (t==NULL) return; TREE_T *b=tree_get(backup,t->s); b->value=t->value; tree_commit(backup,t->lt); tree_commit(backup,t->gt); free(t); }
void ydb_prefetch(YDB ydb, char **keys, unsigned short *key_szs, int items_counter) { struct db *db = (struct db *) ydb; assert(db->magic == YDB_STRUCT_MAGIC); struct item **items_start = (struct item **)malloc(sizeof(struct item_index *) * items_counter); struct item **items = items_start; DB_LOCK(db); int i; for(i=0; i < items_counter; i++, keys++, key_szs++) { char *key = *keys; int key_sz = *key_szs; struct item *item = tree_get(db->tree, key, key_sz); if(item) { *items = item; items++; } } DB_UNLOCK(db); int items_sz = items - items_start; qsort(items_start, items_sz, sizeof(struct item *), item_cmp); items = items_start; int fd = -1; int count = 0; int offset = 0; for(i=0; i < items_sz; i++, items++) { struct item *item = *items; struct log *log = slot_get(db->loglist, item->logno); size_t read_size = ROUND_UP(item->value_sz, PADDING) + sizeof(struct ydb_value_record); /* merge? */ if(fd == log->fd && (offset + count + 4096) >= item->value_offset) { count = (item->value_offset+read_size) - offset; }else{ if(fd != log->fd) { /* clear previous fadvices */ posix_fadvise(log->fd, 0, 0, POSIX_FADV_RANDOM); } if(fd != -1) { posix_fadvise(fd, offset, count, POSIX_FADV_WILLNEED); } fd = log->fd; count = read_size; offset = item->value_offset; } } if(fd != -1) { posix_fadvise(fd, offset, count, POSIX_FADV_WILLNEED); } free(items_start); }
int tree_add(tree t, void * e) { int boolean = 0; boolean = tree_get(t,e) != NULL; if (!boolean) { t->header = Binary_Tree(t, e, t->header, t->H, &boolean); t->size++; } return !boolean; }
void tree_close(void) { if (shared_tree) tree_flush(tree_get()); shared_tree = NULL; if (shared_tree_lock) { lock_destroy(shared_tree_lock); lock_dealloc(shared_tree_lock); shared_tree_lock=0; } }
static struct qr_message * get_message(uint32_t msgid) { struct qr_message *msg; msg = tree_get(&messages, msgid); if (msg == NULL) log_warn("warn: queue-ram: message not found"); return (msg); }
char * build_realname(struct fuse *f, ino_t ino) { struct fuse_vnode *vn; char *name = strdup("/"); char *tmp = NULL; int firstshot = 0; vn = tree_get(&f->vnode_tree, ino); if (!vn || !name) { free(name); return (NULL); } while (vn->parent != 0) { if (firstshot++) asprintf(&tmp, "/%s%s", vn->path, name); else asprintf(&tmp, "/%s", vn->path); if (tmp == NULL) { free(name); return (NULL); } free(name); name = tmp; tmp = NULL; vn = tree_get(&f->vnode_tree, vn->parent); if (!vn) return (NULL); } if (ino == (ino_t)0) DPRINTF("%s: NULL ino\n", __func__); DPRINTF("realname %s\n", name); return (name); }
/* * Linux specific routines */ void plinnames_collect(TABLE tab) { char *basename; plinnames_sysfiles = tree_create(); plinnames_readalldir("/proc/sys", plinnames_sysfiles); tree_traverse(plinnames_sysfiles) { table_addemptyrow(tab); table_replacecurrentcell(tab, "value", tree_get(plinnames_sysfiles)); table_replacecurrentcell(tab, "name", tree_getkey(plinnames_sysfiles)); basename = strrchr(tree_getkey(plinnames_sysfiles), '/'); if (basename) basename++; else basename = tree_getkey(plinnames_sysfiles); table_replacecurrentcell(tab, "vname", basename); table_freeondestroy(tab, tree_getkey(plinnames_sysfiles)); table_freeondestroy(tab, tree_get(plinnames_sysfiles)); } tree_destroy(plinnames_sysfiles); }
void keyValue(char a[][30] ,int n) { int i; TREE_T *root=tree_new("m for root"); TREE_T *backup=tree_load(); for(i=0;i<n;i++) { char *p=a[i]; int value; char name[MAXN+1]; TREE_T *t; switch(p[0]) { case 'S': sscanf(p,"SET %s %d",&name,&value); t=tree_get(root,name); t->value=value; break; case 'G': sscanf(p,"GET %s",&name); t=tree_has(root,name); if (!t) t=tree_get(backup,name); printf("%d\n",t->value); break; case 'R': tree_free(root); root=tree_new("m for root"); break; case 'C': tree_commit(backup,root); root=tree_new("m for root"); break; default: assert(0); } } tree_free(root); tree_save(backup); }
static void queue_envelope_cache_update(struct envelope *e) { struct envelope *cached; if ((cached = tree_get(&evpcache_tree, e->id)) == NULL) { queue_envelope_cache_add(e); stat_increment("queue.evpcache.update.missed", 1); } else { TAILQ_REMOVE(&evpcache_list, cached, entry); *cached = *e; TAILQ_INSERT_HEAD(&evpcache_list, cached, entry); stat_increment("queue.evpcache.update.hit", 1); } }
node_t *find_empty_key(tree_t *tree, int *hand, node_t *node) { int key; /* int max = (tree == &(queue_tree))? 49156:MAX_AUTO_ID; for (key = *hand + 1; key <= max; key++) { */ for (key = *hand + 1; key <= MAX_AUTO_ID; key++) { if (!tree_get(tree, key)) { *hand = key; return tree_put(tree, key, node); } } /* TODO test */ for (key = MIN_AUTO_ID; key < *hand; key++) { if (!tree_get(tree, key)) { *hand = key; return tree_put(tree, key, node); } } return NULL; }
static int queue_ram_message_commit(uint32_t msgid, const char *path) { struct qr_message *msg; struct stat sb; size_t n; FILE *f; int ret; if ((msg = tree_get(&messages, msgid)) == NULL) { log_warnx("warn: queue-ram: msgid not found"); return (0); } f = fopen(path, "rb"); if (f == NULL) { log_warn("warn: queue-ram: fopen: %s", path); return (0); } if (fstat(fileno(f), &sb) == -1) { log_warn("warn: queue-ram: fstat"); fclose(f); return (0); } msg->len = sb.st_size; msg->buf = malloc(msg->len); if (msg->buf == NULL) { log_warn("warn: queue-ram: malloc"); fclose(f); return (0); } ret = 0; n = fread(msg->buf, 1, msg->len, f); if (ferror(f)) log_warn("warn: queue-ram: fread"); else if ((off_t)n != sb.st_size) log_warnx("warn: queue-ram: bad read"); else { ret = 1; stat_increment("queue.ram.message.size", msg->len); } fclose(f); return (ret); }
// This method should be locked void_p map_get(map m, void_p key) { pthread_mutex_lock(m->mutex); data * finder = (data*) malloc(sizeof(struct data)); finder->key = key; c_index = m->comparer_index; data * d = (data *)tree_get(m->t, finder); free(finder); if (d != NULL) { pthread_mutex_unlock(m->mutex); return d->value; } else { pthread_mutex_unlock(m->mutex); return NULL; } }
int queue_envelope_load(uint64_t evpid, struct envelope *ep) { const char *e; char evpbuf[sizeof(struct envelope)]; size_t evplen; struct envelope *cached; if ((env->sc_queue_flags & QUEUE_EVPCACHE) && (cached = tree_get(&evpcache_tree, evpid))) { *ep = *cached; stat_increment("queue.evpcache.load.hit", 1); return (1); } ep->id = evpid; profile_enter("queue_envelope_load"); evplen = handler_envelope_load(ep->id, evpbuf, sizeof evpbuf); profile_leave(); log_trace(TRACE_QUEUE, "queue-backend: queue_envelope_load(%016"PRIx64") -> %zu", evpid, evplen); if (evplen == 0) return (0); if (queue_envelope_load_buffer(ep, evpbuf, evplen)) { if ((e = envelope_validate(ep)) == NULL) { ep->id = evpid; if (env->sc_queue_flags & QUEUE_EVPCACHE) { queue_envelope_cache_add(ep); stat_increment("queue.evpcache.load.missed", 1); } return (1); } log_debug("debug: invalid envelope %016" PRIx64 ": %s", ep->id, e); } (void)queue_message_corrupt(evpid_to_msgid(evpid)); return (0); }
static int queue_ram_message_fd_r(uint32_t msgid) { struct qr_message *msg; size_t n; FILE *f; int fd, fd2; if ((msg = tree_get(&messages, msgid)) == NULL) { log_warnx("warn: queue-ram: not found"); return (-1); } fd = mktmpfile(); if (fd == -1) { log_warn("warn: queue-ram: mktmpfile"); return (-1); } fd2 = dup(fd); if (fd2 == -1) { log_warn("warn: queue-ram: dup"); close(fd); return (-1); } f = fdopen(fd2, "w"); if (f == NULL) { log_warn("warn: queue-ram: fdopen"); close(fd); close(fd2); return (-1); } n = fwrite(msg->buf, 1, msg->len, f); if (n != msg->len) { log_warn("warn: queue-ram: write"); close(fd); fclose(f); return (-1); } fclose(f); lseek(fd, 0, SEEK_SET); return (fd); }
static int queue_ram_envelope_load(uint64_t evpid, char *buf, size_t len) { struct qr_envelope *evp; struct qr_message *msg; if ((msg = get_message(evpid_to_msgid(evpid))) == NULL) return (0); if ((evp = tree_get(&msg->envelopes, evpid)) == NULL) { log_warn("warn: queue-ram: not found"); return (0); } if (len < evp->len) { log_warnx("warn: queue-ram: buffer too small"); return (0); } memmove(buf, evp->buf, evp->len); return (evp->len); }
static ssize_t addrs_get(backend_t *chain, request_t *request){ ssize_t ret; data_t *temp; off_t def_real_offset; unsigned int def_block_vid; unsigned int def_block_size; off_t *o_real_offset = &def_real_offset; unsigned int *o_block_vid = &def_block_vid; unsigned int *o_block_size = &def_block_size; block_info block; off_t r_virt_key; uint32_t r_block_vid; hash_t *r_virt_key, *r_block_vid; addrs_userdata *data = (addrs_userdata *)chain->userdata; temp = hash_find_typed(request, TYPE_OFFT, HK(real_offset)); if(temp != NULL) o_real_offset = data_value_ptr(temp); temp = hash_find_typed(request, TYPE_UINT32T, HK(block_vid)); if(temp != NULL) o_block_vid = data_value_ptr(temp); temp = hash_find_typed(request, TYPE_UINT32T, HK(block_size)); if(temp != NULL) o_block_size = data_value_ptr(temp); if(hash_find(request, HK(blocks)) == NULL){ hash_data_copy(ret, TYPE_OFFT, r_virt_key, request, HK(offset)); if(ret != 0) return warning("no offset supplied"); if(tree_get(data->tree, r_virt_key, o_block_vid, o_real_offset) != 0) return -EFAULT; }else{ hash_data_copy(ret, TYPE_UINT32T, r_block_vid, request, HK(block_vid)); if(ret != 0) return warning("no block_vid supplied"); if(tree_get_block(data->tree, r_block_vid, &block) != 0) return -EFAULT; *o_real_offset = (off_t)(block.real_block_off); *o_block_size = (unsigned int)(block.size); } return 0; }
int tree_swap(struct tree_item *root) { struct tree *new_tree, *old_tree; new_tree = tree_alloc(); if (NULL == new_tree) return -1; new_tree->root = root; /* Save old tree */ old_tree = tree_get(); /* Critical - swap trees */ lock_get(shared_tree_lock); *shared_tree = new_tree; lock_release(shared_tree_lock); /* Flush old tree */ tree_flush(old_tree); return 0; }
/* ARGSUSED */ static void control_accept(int listenfd, short event, void *arg) { int connfd; socklen_t len; struct sockaddr_un sun; struct ctl_conn *c; size_t *count; uid_t euid; gid_t egid; if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE) goto pause; len = sizeof(sun); if ((connfd = accept(listenfd, (struct sockaddr *)&sun, &len)) == -1) { if (errno == ENFILE || errno == EMFILE) goto pause; if (errno == EINTR || errno == EWOULDBLOCK || errno == ECONNABORTED) return; fatal("control_accept: accept"); } session_socket_blockmode(connfd, BM_NONBLOCK); if (getpeereid(connfd, &euid, &egid) == -1) fatal("getpeereid"); count = tree_get(&ctl_count, euid); if (count == NULL) { count = xcalloc(1, sizeof *count, "control_accept"); tree_xset(&ctl_count, euid, count); } if (*count == CONTROL_MAXCONN_PER_CLIENT) { close(connfd); log_warnx("warn: too many connections to control socket " "from user with uid %lu", (unsigned long int)euid); return; } (*count)++; c = xcalloc(1, sizeof(*c), "control_accept"); c->euid = euid; c->egid = egid; c->id = ++connid; c->mproc.proc = PROC_CLIENT; c->mproc.handler = control_dispatch_ext; c->mproc.data = c; mproc_init(&c->mproc, connfd); mproc_enable(&c->mproc); tree_xset(&ctl_conns, c->id, c); stat_backend->increment("control.session", 1); return; pause: log_warnx("warn: ctl client limit hit, disabling new connections"); event_del(&control_state.ev); }
/* * Carry out aggregation on a complete data set held in a table * This is an alternative entry point to the class that does not need * the setting up of a session. * The table should identify keys, time, sequence and duration in the * standard way as defined by FHA spec. * Returns a TABLE of results compliant to the FHA spec, _time will be * set to the last time of the dataset, _seq to 0. _dur is not set * The result is independent of dataset's memory allocation, sothe caller * needs to run table_destroy() to free its memory. * Returns NULL if there is an error, if dataset is NULL or if there * was insufficent data. */ TABLE cascade_aggregate(enum cascade_fn func, /* aggregation function */ TABLE dataset /* multi-sample, multi-key * dataset in a table */ ) { TREE *inforow, *keyvals, *databykey, *colnames; char *keycol, *colname, *tmpstr, *type; int duration, haskey=0; TABLE itab, result; TABSET tset; ITREE *col; double val, tmpval1, tmpval2; time_t t1, t2, tdiff; /* assert special cases */ if ( ! dataset ) { elog_printf(DIAG, "no dataset given to aggregate"); return NULL; } if (table_nrows(dataset) == 0) { elog_printf(DIAG, "no rows to aggregate in dataset"); } if ( ! table_hascol(dataset, "_time")) { tmpstr = table_outheader(dataset); elog_printf(ERROR, "attempting to aggregate a table without _time " "column (columns: %s)", tmpstr); nfree(tmpstr); return NULL; } /* find any keys that might exist */ inforow = table_getinforow(dataset, "key"); if (inforow) { keycol = tree_search(inforow, "1", 2); if (keycol) { keyvals = table_uniqcolvals(dataset, keycol, NULL); if (keyvals) { /* separate the combined data set into ones of * separate keys */ haskey++; databykey = tree_create(); tset = tableset_create(dataset); tree_traverse(keyvals) { /* select out the data */ tableset_reset(tset); tableset_where(tset, keycol, eq, tree_getkey(keyvals)); itab = tableset_into(tset); tree_add(databykey, tree_getkey(keyvals), itab); } tableset_destroy(tset); } tree_destroy(keyvals); } tree_destroy(inforow); } /* if there were no keys found, pretend that we have a single one */ if ( ! haskey ) { databykey = tree_create(); tree_add(databykey, "nokey", dataset); } /* find the time span and duration of the dataset */ table_first(dataset); if (table_hascol(dataset, "_dur")) duration = strtol(table_getcurrentcell(dataset, "_dur"), NULL, 10); else duration = 0; t1 = strtol(table_getcurrentcell(dataset, "_time"), NULL, 10); table_last(dataset); t2 = strtol(table_getcurrentcell(dataset, "_time"), NULL, 10); tdiff = t2-t1+duration; /* go over the keyed table and apply our operators to each column * in turn */ result = table_create_fromdonor(dataset); table_addcol(result, "_seq", NULL); /* make col before make row */ table_addcol(result, "_time", NULL); table_addcol(result, "_dur", NULL); tree_traverse(databykey) { table_addemptyrow(result); itab = tree_get(databykey); colnames = table_getheader(itab); tree_traverse(colnames) { colname = tree_getkey(colnames); if ( ! table_hascol(result, colname)) { tmpstr = xnstrdup(colname); table_addcol(result, tmpstr, NULL); table_freeondestroy(result, tmpstr); } col = table_getcol(itab, colname); type = table_getinfocell(itab, "type", colname); if (type && strcmp(type, "str") == 0) { /* string value: report the last one */ itree_last(col); table_replacecurrentcell(result, colname, itree_get(col)); } else if (strcmp(colname, "_dur") == 0) { /* _dur: use the last value, can treat as string */ itree_last(col); table_replacecurrentcell(result, "_dur", itree_get(col)); } else if (strcmp(colname, "_seq") == 0) { /* _seq: only one result is produced so must be 0 */ table_replacecurrentcell(result, "_seq", "0"); } else if (strcmp(colname, "_time") == 0) { /* _time: use the last value, can treat as string */ itree_last(col); table_replacecurrentcell(result, "_time", itree_get(col)); } else { /* numeric value: treat as a float and report it */ switch (func) { case CASCADE_AVG: /* average of column's values */ val = 0.0; itree_traverse(col) val += atof( itree_get(col) ); val = val / itree_n(col); break; case CASCADE_MIN: /* minimum of column's values */ val = DBL_MAX; itree_traverse(col) { tmpval1 = atof( itree_get(col) ); if (tmpval1 < val) val = tmpval1; } break; case CASCADE_MAX: /* maximum of column's values */ val = DBL_MIN; itree_traverse(col) { tmpval1 = atof( itree_get(col) ); if (tmpval1 > val) val = tmpval1; } break; case CASCADE_SUM: /* sum of column's values */ val = 0.0; itree_traverse(col) val += atof( itree_get(col) ); break; case CASCADE_LAST: /* last value */ itree_last(col); val = atof( itree_get(col) ); break; case CASCADE_FIRST: /* last value */ itree_first(col); val = atof( itree_get(col) ); break; case CASCADE_DIFF: /* the difference in values of first and last */ itree_first(col); tmpval1 = atof( itree_get(col) ); itree_last(col); tmpval2 = atof( itree_get(col) ); val = tmpval2 - tmpval1; break; case CASCADE_RATE: /* difference in values (as CASCADE_DIFF) then * divided by the number of seconds in the set */ itree_first(col); tmpval1 = atof( itree_get(col) ); itree_last(col); tmpval2 = atof( itree_get(col) ); val = tmpval2 - tmpval1; val = val / tdiff; break; } /* save the floating point value */ table_replacecurrentcell_alloc(result, colname, util_ftoa(val)); } itree_destroy(col); } /* make sure that there are values for the special columns */ if ( ! table_hascol(dataset, "_time")) table_replacecurrentcell(result, "_time", util_decdatetime(time(NULL))); if ( ! table_hascol(dataset, "_seq")) table_replacecurrentcell(result, "_seq", "0"); if ( ! table_hascol(dataset, "_dur")) table_replacecurrentcell(result, "_dur", "0"); } /* clear up */ if (haskey) { tree_traverse(databykey) { itab = tree_get(databykey); table_destroy(itab); } } tree_destroy(databykey); return result; }
void tree_close(void) { tree_flush(tree_get()); }
static void control_imsg(struct mproc *p, struct imsg *imsg) { struct ctl_conn *c; struct stat_value val; struct msg m; const char *key; const void *data; size_t sz; if (p->proc == PROC_PONY) { switch (imsg->hdr.type) { case IMSG_CTL_SMTP_SESSION: c = tree_get(&ctl_conns, imsg->hdr.peerid); if (c == NULL) return; m_compose(&c->mproc, IMSG_CTL_OK, 0, 0, imsg->fd, NULL, 0); return; } } if (p->proc == PROC_SCHEDULER) { switch (imsg->hdr.type) { case IMSG_CTL_OK: case IMSG_CTL_FAIL: case IMSG_CTL_LIST_MESSAGES: c = tree_get(&ctl_conns, imsg->hdr.peerid); if (c == NULL) return; imsg->hdr.peerid = 0; m_forward(&c->mproc, imsg); return; } } if (p->proc == PROC_QUEUE) { switch (imsg->hdr.type) { case IMSG_CTL_LIST_ENVELOPES: case IMSG_CTL_DISCOVER_EVPID: case IMSG_CTL_DISCOVER_MSGID: case IMSG_CTL_UNCORRUPT_MSGID: c = tree_get(&ctl_conns, imsg->hdr.peerid); if (c == NULL) return; m_forward(&c->mproc, imsg); return; } } if (p->proc == PROC_PONY) { switch (imsg->hdr.type) { case IMSG_CTL_OK: case IMSG_CTL_FAIL: case IMSG_CTL_MTA_SHOW_HOSTS: case IMSG_CTL_MTA_SHOW_RELAYS: case IMSG_CTL_MTA_SHOW_ROUTES: case IMSG_CTL_MTA_SHOW_HOSTSTATS: case IMSG_CTL_MTA_SHOW_BLOCK: c = tree_get(&ctl_conns, imsg->hdr.peerid); if (c == NULL) return; imsg->hdr.peerid = 0; m_forward(&c->mproc, imsg); return; } } switch (imsg->hdr.type) { case IMSG_STAT_INCREMENT: m_msg(&m, imsg); m_get_string(&m, &key); m_get_data(&m, &data, &sz); m_end(&m); memmove(&val, data, sz); if (stat_backend) stat_backend->increment(key, val.u.counter); control_digest_update(key, val.u.counter, 1); return; case IMSG_STAT_DECREMENT: m_msg(&m, imsg); m_get_string(&m, &key); m_get_data(&m, &data, &sz); m_end(&m); memmove(&val, data, sz); if (stat_backend) stat_backend->decrement(key, val.u.counter); control_digest_update(key, val.u.counter, 0); return; case IMSG_STAT_SET: m_msg(&m, imsg); m_get_string(&m, &key); m_get_data(&m, &data, &sz); m_end(&m); memmove(&val, data, sz); if (stat_backend) stat_backend->set(key, &val); return; } errx(1, "control_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); }
void mta_imsg(struct imsgev *iev, struct imsg *imsg) { struct mta_route *route; struct mta_batch2 *batch; struct mta_task *task; struct envelope *e; struct ssl *ssl; uint64_t id; if (iev->proc == PROC_QUEUE) { switch (imsg->hdr.type) { case IMSG_BATCH_CREATE: id = *(uint64_t*)(imsg->data); batch = xmalloc(sizeof *batch, "mta_batch"); batch->id = id; tree_init(&batch->tasks); tree_xset(&batches, batch->id, batch); log_trace(TRACE_MTA, "mta: batch:%016" PRIx64 " created", batch->id); return; case IMSG_BATCH_APPEND: e = xmemdup(imsg->data, sizeof *e, "mta:envelope"); route = mta_route_for(e); batch = tree_xget(&batches, e->batch_id); if ((task = tree_get(&batch->tasks, route->id)) == NULL) { log_trace(TRACE_MTA, "mta: new task for %s", mta_route_to_text(route)); task = xmalloc(sizeof *task, "mta_task"); TAILQ_INIT(&task->envelopes); task->route = route; tree_xset(&batch->tasks, route->id, task); task->msgid = evpid_to_msgid(e->id); task->sender = e->sender; route->refcount += 1; } /* Technically, we could handle that by adding a msg * level, but the batch sent by the scheduler should * be valid. */ if (task->msgid != evpid_to_msgid(e->id)) errx(1, "msgid mismatch in batch"); /* XXX honour route->maxrcpt */ TAILQ_INSERT_TAIL(&task->envelopes, e, entry); stat_increment("mta.envelope", 1); log_debug("mta: received evp:%016" PRIx64 " for <%s@%s>", e->id, e->dest.user, e->dest.domain); return; case IMSG_BATCH_CLOSE: id = *(uint64_t*)(imsg->data); batch = tree_xpop(&batches, id); log_trace(TRACE_MTA, "mta: batch:%016" PRIx64 " closed", batch->id); /* for all tasks, queue them on there route */ while (tree_poproot(&batch->tasks, &id, (void**)&task)) { if (id != task->route->id) errx(1, "route id mismatch!"); task->route->refcount -= 1; task->route->ntask += 1; TAILQ_INSERT_TAIL(&task->route->tasks, task, entry); stat_increment("mta.task", 1); mta_route_drain(task->route); } free(batch); return; case IMSG_QUEUE_MESSAGE_FD: mta_session_imsg(iev, imsg); return; } } if (iev->proc == PROC_LKA) { switch (imsg->hdr.type) { case IMSG_LKA_SECRET: case IMSG_DNS_HOST: case IMSG_DNS_HOST_END: case IMSG_DNS_PTR: mta_session_imsg(iev, imsg); return; } } if (iev->proc == PROC_PARENT) { switch (imsg->hdr.type) { case IMSG_CONF_START: if (env->sc_flags & SMTPD_CONFIGURING) return; env->sc_flags |= SMTPD_CONFIGURING; env->sc_ssl = xcalloc(1, sizeof *env->sc_ssl, "mta:sc_ssl"); return; case IMSG_CONF_SSL: if (!(env->sc_flags & SMTPD_CONFIGURING)) return; ssl = xmemdup(imsg->data, sizeof *ssl, "mta:ssl"); ssl->ssl_cert = xstrdup((char*)imsg->data + sizeof *ssl, "mta:ssl_cert"); ssl->ssl_key = xstrdup((char*)imsg->data + sizeof *ssl + ssl->ssl_cert_len, "mta:ssl_key"); SPLAY_INSERT(ssltree, env->sc_ssl, ssl); return; case IMSG_CONF_END: if (!(env->sc_flags & SMTPD_CONFIGURING)) return; env->sc_flags &= ~SMTPD_CONFIGURING; return; case IMSG_CTL_VERBOSE: log_verbose(*(int *)imsg->data); return; } } errx(1, "mta_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); }
injection_t * injection_get(const process_t * process, const injectable_t * injectable) { return tree_get(&process->injections, (tree_key_t) injectable); }