static int pd_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); Quote *quote = (Quote *)msg->data; dlist_t dlist; NOT_USED(data2); if ((dlist = table_get_value(contracts, quote->thyquote.m_cHYDM))) { dlist_iter_t iter = dlist_iter_new(dlist, DLIST_START_HEAD); dlist_node_t node; while ((node = dlist_next(iter))) { struct cpl *cpl = (struct cpl *)dlist_node_value(node); pthread_spin_lock(&cpl->lock); if (!strcasecmp(cpl->contract1, quote->thyquote.m_cHYDM)) cpl->price1 = quote->thyquote.m_dZXJ; else cpl->price2 = quote->thyquote.m_dZXJ; if (cpl->price1 > 0.0 && cpl->price2 > 0.0) { float pd = fabs(cpl->price1 - cpl->price2); /* If the price diff changes, we output it. */ if (fabs(pd - cpl->prevpd) > 0.000001) { time_t t = (time_t)quote->thyquote.m_nTime; struct tm lt; char datestr[64], res[512]; strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, sizeof res, "PD,%s.%03d,%s,%s|%.2f,%.2f,%.2f", datestr, quote->m_nMSec, cpl->contract1, cpl->contract2, cpl->price1, cpl->price2, pd); out2rmp(res); cpl->prevpd = pd; } } pthread_spin_unlock(&cpl->lock); } } return 0; }
/* Sorts the list basing on the period, getting a rate-monotonic priority * assignment */ static int set_rm_priorities (dlist_t **threads, int minprio) { diter_t *i; dlist_t *ts; /* Sort by period */ ts = *threads = dlist_sort(*threads, (dcmp_func_t) prio_cmp); i = dlist_iter_new(&ts); /* Assign priorities */ while (diter_hasnext(i)) { thrd_t *t; t = (thrd_t *) diter_next(i); t->priority = minprio ++; } dlist_iter_free(i); return 0; }
int thrd_start (thrd_pool_t *pool) { diter_t *i; int err; struct timespec now; if (dlist_empty(pool->threads)) { pool->status |= THRD_ERR_EMPTY; return -1; } /* We need to bulid the priority set the first time. * * Currently this "first time" check is useless, since for the moment * this structure is not supporting thread stopping. */ if ((pool->status & THRD_POOL_SORTED) == 0) { if (set_rm_priorities(&pool->threads, pool->minprio) == -1) { pool->status |= THRD_ERR_NULLPER; return -1; } } /* Start each thread. */ pool->status |= THRD_POOL_ACTIVE; i = dlist_iter_new(&pool->threads); rtutils_get_now(&now); while (diter_hasnext(i)) { err = startup((thrd_t *) diter_next(i), &now); if (err) { pool->status |= THRD_ERR_LIBRARY; pool->err = err; dlist_iter_free(i); return -1; } } dlist_iter_free(i); return 0; }
int main (int argc, char **argv) { mbox_err_t err; mbox_t *mbox; mbox_mail_t *mail; assert(argc > 1); err = mbox_new(argv[1], &mbox); if (err) { fprintf(stderr, "Mbox error: %s\n", mbox_strerr(err)); exit(1); } printf("Starting to get milk\n"); while ((mail = mbox_next_mail (mbox)) != NULL) { const dlist_t *trace; diter_t *iter; printf("Is to [%s]\n", mbox_mail_getattr(mail, "To")); printf("Mail trace:\n"); trace = mbox_mail_gettrace(mail); iter = dlist_iter_new((dlist_t **)&trace); while (diter_hasnext(iter)) { printf("\t%s\n", (char *)diter_next(iter)); } dlist_iter_free(iter); printf("FOLLOWING TEXT\n"); printf("%s\n", mbox_mail_getbody(mail)); printf("END OF TEXT\n"); mbox_mail_free(mail); } printf("LOL WUT?\n"); mbox_free(mbox); exit(0); }
static void read_quote(event_loop el, int fd, int mask, void *data) { char *buf; struct sockaddr_in si; socklen_t slen = sizeof si; int nread; NOT_USED(el); NOT_USED(mask); NOT_USED(data); if ((buf = CALLOC(1, sizeof (Quote))) == NULL) return; /* FIXME */ if ((nread = recvfrom(fd, buf, sizeof (Quote), 0, (struct sockaddr *)&si, &slen)) > 0) { Quote *quote; struct msg *msg; quote = (Quote *)buf; if (quote->thyquote.m_nLen == sizeof (THYQuote)) { int tlen; quote->thyquote.m_cJYS[sizeof quote->thyquote.m_cJYS - 1] = '\0'; quote->thyquote.m_cHYDM[sizeof quote->thyquote.m_cHYDM - 1] = '\0'; quote->m_nMSec = 0; /* for testing */ dlist_rwlock_rdlock(monitors); if (dlist_length(monitors) > 0) { char res[512]; dlist_iter_t iter = dlist_iter_new(monitors, DLIST_START_HEAD); dlist_node_t node; snprintf(res, sizeof res, "RX '%d,%s,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f," "%.2f,%.2f,%d,%.2f,%d,%d,%.2f,%d,%.2f,%d'\r\n", quote->thyquote.m_nTime, quote->thyquote.m_cHYDM, quote->thyquote.m_cJYS, quote->thyquote.m_dZXJ, quote->thyquote.m_dJKP, quote->thyquote.m_dZGJ, quote->thyquote.m_dZDJ, quote->thyquote.m_dZSP, quote->thyquote.m_dJSP, quote->thyquote.m_dZJSJ, quote->thyquote.m_dJJSJ, quote->thyquote.m_nCJSL, quote->thyquote.m_dCJJE, quote->thyquote.m_nZCCL, quote->thyquote.m_nCCL, quote->thyquote.m_dMRJG1, quote->thyquote.m_nMRSL1, quote->thyquote.m_dMCJG1, quote->thyquote.m_nMCSL1); while ((node = dlist_next(iter))) { client c = (client)dlist_node_value(node); pthread_spin_lock(&c->lock); if (c->flags & CLIENT_CLOSE_ASAP) { pthread_spin_unlock(&c->lock); continue; } if (net_try_write(c->fd, res, strlen(res), 10, NET_NONBLOCK) == -1) { xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", c, strerror(errno)); if (++c->eagcount >= 10) client_free_async(c); } else if (c->eagcount) c->eagcount = 0; pthread_spin_unlock(&c->lock); } dlist_iter_free(&iter); } dlist_rwlock_unlock(monitors); /* FIXME */ if (quote->thyquote.m_nTime == 999999999) { FREE(buf); return; } else if ((tlen = intlen(quote->thyquote.m_nTime)) < 10) { struct timeval tv; struct tm lt; gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, <); if (quote->thyquote.m_cHYDM[0] == 'S' && quote->thyquote.m_cHYDM[1] == 'P') quote->thyquote.m_nTime *= 1000; else if (tlen == 6 || tlen == 7) quote->thyquote.m_nTime *= 100; lt.tm_hour = quote->thyquote.m_nTime / 10000000; lt.tm_min = quote->thyquote.m_nTime % 10000000 / 100000; lt.tm_sec = quote->thyquote.m_nTime % 100000 / 1000; quote->m_nMSec = quote->thyquote.m_nTime % 1000; quote->thyquote.m_nTime = mktime(<); } /* FIXME */ if (addms) { struct timeval tv; dstr contract = dstr_new(quote->thyquote.m_cHYDM); struct sms *sms; gettimeofday(&tv, NULL); if ((sms = table_get_value(times, contract)) == NULL) { if (NEW(sms)) { sms->qsec = quote->thyquote.m_nTime; sms->sec = tv.tv_sec; sms->msec = tv.tv_usec / 1000; table_insert(times, contract, sms); } } else if (sms->qsec != quote->thyquote.m_nTime) { sms->qsec = quote->thyquote.m_nTime; sms->sec = tv.tv_sec; sms->msec = tv.tv_usec / 1000; dstr_free(contract); } else { int32_t offset; if ((offset = (tv.tv_sec - sms->sec) * 1000 + tv.tv_usec / 1000 - sms->msec) > 999) offset = 999; quote->m_nMSec = offset; dstr_free(contract); } } } if (NEW0(msg) == NULL) { FREE(buf); return; } msg->data = buf; msg->refcount = 1; thrpool_queue(tp, send_quote, msg, NULL, msgfree, NULL); } else FREE(buf); }
static int send_quote(void *data, void *data2) { struct msg *msg = (struct msg *)data; Quote *quote; int status; NOT_USED(data2); quote = (Quote *)msg->data; if (quote->thyquote.m_nLen == sizeof (THYQuote)) { if (get_logger_level() == __LOG_DEBUG) { time_t t = (time_t)quote->thyquote.m_nTime; char datestr[64]; strftime(datestr, sizeof datestr, "%F %T", localtime(&t)); xcb_log(XCB_LOG_DEBUG, "%s.%03d,%s,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f," "%d,%.2f,%d,%d,%.2f,%d,%.2f,%d", datestr, quote->m_nMSec, quote->thyquote.m_cHYDM, quote->thyquote.m_cJYS, quote->thyquote.m_dZXJ, quote->thyquote.m_dJKP, quote->thyquote.m_dZGJ, quote->thyquote.m_dZDJ, quote->thyquote.m_dZSP, quote->thyquote.m_dJSP, quote->thyquote.m_dZJSJ, quote->thyquote.m_dJJSJ, quote->thyquote.m_nCJSL, quote->thyquote.m_dCJJE, quote->thyquote.m_nZCCL, quote->thyquote.m_nCCL, quote->thyquote.m_dMRJG1, quote->thyquote.m_nMRSL1, quote->thyquote.m_dMCJG1, quote->thyquote.m_nMCSL1); } /* for testing */ dlist_rwlock_rdlock(monitors); if (dlist_length(monitors) > 0) { char res[512]; dlist_iter_t iter = dlist_iter_new(monitors, DLIST_START_HEAD); dlist_node_t node; snprintf(res, sizeof res, "TX '%d,%s,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f," "%d,%.2f,%d,%d,%.2f,%d,%.2f,%d'\r\n", quote->thyquote.m_nTime, quote->thyquote.m_cHYDM, quote->thyquote.m_cJYS, quote->thyquote.m_dZXJ, quote->thyquote.m_dJKP, quote->thyquote.m_dZGJ, quote->thyquote.m_dZDJ, quote->thyquote.m_dZSP, quote->thyquote.m_dJSP, quote->thyquote.m_dZJSJ, quote->thyquote.m_dJJSJ, quote->thyquote.m_nCJSL, quote->thyquote.m_dCJJE, quote->thyquote.m_nZCCL, quote->thyquote.m_nCCL, quote->thyquote.m_dMRJG1, quote->thyquote.m_nMRSL1, quote->thyquote.m_dMCJG1, quote->thyquote.m_nMCSL1); while ((node = dlist_next(iter))) { client c = (client)dlist_node_value(node); pthread_spin_lock(&c->lock); if (c->flags & CLIENT_CLOSE_ASAP) { pthread_spin_unlock(&c->lock); continue; } if (net_try_write(c->fd, res, strlen(res), 10, NET_NONBLOCK) == -1) { xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", c, strerror(errno)); if (++c->eagcount >= 10) client_free_async(c); } else if (c->eagcount) c->eagcount = 0; pthread_spin_unlock(&c->lock); } dlist_iter_free(&iter); } dlist_rwlock_unlock(monitors); } /* FIXME */ if ((status = pgm_send(pgm_sender, msg->data, sizeof (Quote), NULL)) != PGM_IO_STATUS_NORMAL) xcb_log(XCB_LOG_WARNING, "Sending data failed"); msg_decr(msg); return 0; }
static int server_cron(event_loop el, unsigned long id, void *data) { dlist_iter_t iter; dlist_node_t node; NOT_USED(el); NOT_USED(id); NOT_USED(data); if (log_reload) { close_logger(); if (init_logger("/var/log/xcb/xcb-dp2.log", __LOG_DEBUG) == 0) { const char *tmp; pthread_mutex_lock(&cfg_lock); if ((tmp = variable_retrieve(cfg, "general", "log_level"))) { if (!strcasecmp(tmp, "debug")) set_logger_level(__LOG_DEBUG); else if (!strcasecmp(tmp, "info")) set_logger_level(__LOG_INFO); else if (!strcasecmp(tmp, "notice")) set_logger_level(__LOG_NOTICE); else if (!strcasecmp(tmp, "warning")) set_logger_level(__LOG_WARNING); } pthread_mutex_unlock(&cfg_lock); log_reload = 0; } /* FIXME */ if (addms) table_clear(times); } if (shut_down) { if (prepare_for_shutdown() == 0) exit(0); xcb_log(XCB_LOG_WARNING, "SIGTERM received, but errors trying to shutdown the server"); } /* FIXME */ iter = dlist_iter_new(clients_to_close, DLIST_START_HEAD); while ((node = dlist_next(iter))) { client c = (client)dlist_node_value(node); if (c->refcount == 0) client_free(c); } dlist_iter_free(&iter); /* FIXME */ if (cronloops % 200 == 0) { char meme[] = "SU OT GNOLEB ERA ESAB RUOY LLA"; int status; /* heartbeat */ dlist_lock(clients); if (dlist_length(clients) > 0) { dstr res = dstr_new("HEARTBEAT|"); dstr ip = getipv4(); res = dstr_cat(res, ip); res = dstr_cat(res, "\r\n"); iter = dlist_iter_new(clients, DLIST_START_HEAD); while ((node = dlist_next(iter))) { client c = (client)dlist_node_value(node); pthread_spin_lock(&c->lock); if (net_try_write(c->fd, res, dstr_length(res), 100, NET_NONBLOCK) == -1) xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", c, strerror(errno)); pthread_spin_unlock(&c->lock); } dlist_iter_free(&iter); dstr_free(ip); dstr_free(res); } dlist_unlock(clients); /* FIXME: trying to lower the high CPU load while idle */ if ((status = pgm_send(pgm_sender, meme, sizeof meme, NULL)) != PGM_IO_STATUS_NORMAL) xcb_log(XCB_LOG_WARNING, "Communication test failed"); } ++cronloops; return 100; }
void process_quote(void *data) { Quote *quote; struct msg *msg; quote = (Quote *)data; if (quote->thyquote.m_nLen == sizeof (tHYQuote)) { dlist_iter_t iter; dlist_node_t node; int tlen; quote->thyquote.m_cJYS[sizeof quote->thyquote.m_cJYS - 1] = '\0'; quote->thyquote.m_cHYDM[sizeof quote->thyquote.m_cHYDM - 1] = '\0'; quote->m_nMSec = 0; /* in case of multiple monitors */ dlist_rwlock_rdlock(monitors); if (dlist_length(monitors) > 0) { char res[512]; snprintf(res, sizeof res, "RX '%d,%s,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f," "%.2f,%.2f,%d,%.2f,%d,%d,%.2f,%d,%.2f,%d'\r\n", quote->thyquote.m_nTime, quote->thyquote.m_cHYDM, quote->thyquote.m_cJYS, quote->thyquote.m_dZXJ, quote->thyquote.m_dJKP, quote->thyquote.m_dZGJ, quote->thyquote.m_dZDJ, quote->thyquote.m_dZSP, quote->thyquote.m_dJSP, quote->thyquote.m_dZJSJ, quote->thyquote.m_dJJSJ, quote->thyquote.m_nCJSL, quote->thyquote.m_dCJJE, quote->thyquote.m_nZCCL, quote->thyquote.m_nCCL, quote->thyquote.m_dMRJG1, quote->thyquote.m_nMRSL1, quote->thyquote.m_dMCJG1, quote->thyquote.m_nMCSL1); iter = dlist_iter_new(monitors, DLIST_START_HEAD); while ((node = dlist_next(iter))) { client c = (client)dlist_node_value(node); pthread_spin_lock(&c->lock); if (!(c->flags & CLIENT_CLOSE_ASAP)) { if (net_try_write(c->fd, res, strlen(res), 10, NET_NONBLOCK) == -1) { xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", c, strerror(errno)); if (++c->eagcount >= 3) client_free_async(c); } else if (c->eagcount) c->eagcount = 0; } pthread_spin_unlock(&c->lock); } dlist_iter_free(&iter); } dlist_rwlock_unlock(monitors); /* FIXME */ if (quote->thyquote.m_nTime == 999999999) { FREE(data); return; /* idiosyncrasy of different timestamps */ } else if ((tlen = intlen(quote->thyquote.m_nTime)) < 10) { int hour; struct tm lt; hour = quote->thyquote.m_nTime / 10000000; if (tv.tv_sec == 0 || hour == 9 || hour == 21) gettimeofday(&tv, NULL); if (prev_hour == 23 && hour == 0) tv.tv_sec += 24 * 60 * 60; prev_hour = hour; localtime_r(&tv.tv_sec, <); if (quote->thyquote.m_cHYDM[0] == 'S' && quote->thyquote.m_cHYDM[1] == 'P') quote->thyquote.m_nTime *= 1000; else if (tlen == 6 || tlen == 7) quote->thyquote.m_nTime *= 100; lt.tm_sec = quote->thyquote.m_nTime % 100000 / 1000; lt.tm_min = quote->thyquote.m_nTime % 10000000 / 100000; lt.tm_hour = hour; quote->m_nMSec = quote->thyquote.m_nTime % 1000; quote->thyquote.m_nTime = mktime(<); } /* FIXME: no millisecond field in some exchanges' quotes */ if (addms) { struct timeval tv; dstr contract = dstr_new(quote->thyquote.m_cHYDM); struct sms *sms; gettimeofday(&tv, NULL); if ((sms = table_get_value(times, contract)) == NULL) { if (NEW(sms)) { sms->qsec = quote->thyquote.m_nTime; sms->sec = tv.tv_sec; sms->msec = tv.tv_usec / 1000; table_insert(times, contract, sms); } } else if (sms->qsec != quote->thyquote.m_nTime) { sms->qsec = quote->thyquote.m_nTime; sms->sec = tv.tv_sec; sms->msec = tv.tv_usec / 1000; dstr_free(contract); } else { int32_t offset; if ((offset = (tv.tv_sec - sms->sec) * 1000 + tv.tv_usec / 1000 - sms->msec) > 999) offset = 999; quote->m_nMSec = offset; dstr_free(contract); } } if (get_logger_level() == __LOG_DEBUG) { time_t t = (time_t)quote->thyquote.m_nTime; char datestr[64]; strftime(datestr, sizeof datestr, "%F %T", localtime(&t)); xcb_log(XCB_LOG_DEBUG, "%s.%03d,%s,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f," "%d,%.2f,%d,%d,%.2f,%d,%.2f,%d", datestr, quote->m_nMSec, quote->thyquote.m_cHYDM, quote->thyquote.m_cJYS, quote->thyquote.m_dZXJ, quote->thyquote.m_dJKP, quote->thyquote.m_dZGJ, quote->thyquote.m_dZDJ, quote->thyquote.m_dZSP, quote->thyquote.m_dJSP, quote->thyquote.m_dZJSJ, quote->thyquote.m_dJJSJ, quote->thyquote.m_nCJSL, quote->thyquote.m_dCJJE, quote->thyquote.m_nZCCL, quote->thyquote.m_nCCL, quote->thyquote.m_dMRJG1, quote->thyquote.m_nMRSL1, quote->thyquote.m_dMCJG1, quote->thyquote.m_nMCSL1); } } else xcb_log(XCB_LOG_DEBUG, "Data '%s' received", data); if (NEW0(msg) == NULL) { FREE(data); return; } msg->data = data; msg->refcount = 1; thrpool_queue(tp, send_quote, msg, NULL, msgfree, NULL); }
static inline void load_config(void) { /* FIXME */ if ((cfg = config_load("/etc/xcb/vxo.conf"))) { char *cat = category_browse(cfg, NULL); struct variable *var; while (cat) { if (!strcasecmp(cat, "general")) { struct variable *var = variable_browse(cfg, cat); while (var) { if (!strcasecmp(var->name, "inmsg")) { if (strcmp(var->value, "")) inmsg = var->value; } else xcb_log(XCB_LOG_WARNING, "Unknown variable '%s' in " "category '%s' of vxo.conf", var->name, cat); var = var->next; } } else if (!strcasecmp(cat, "expiries")) { var = variable_browse(cfg, cat); while (var) { char *p; if ((p = strrchr(var->name, 'C')) == NULL) p = strrchr(var->name, 'P'); if (p && p != var->name && p != var->name + strlen(var->name) - 1 && ((*(p - 1) == '-' && *(p + 1) == '-') || (isdigit(*(p - 1)) && isdigit(*(p + 1))))) { dstr spotname, strike; struct pd *pd; struct scp *scp; spotname = *(p - 1) == '-' ? dstr_new_len(var->name, p - var->name - 1) : dstr_new_len(var->name, p - var->name); strike = *(p + 1) == '-' ? dstr_new_len(p + 2, var->name + strlen(var->name) - p - 2) : dstr_new_len(p + 1, var->name + strlen(var->name) - p - 1); if ((pd = table_get_value(spots, spotname)) == NULL) { if (NEW(scp)) { scp->strike = atof(strike); scp->cvol = scp->pvol = NAN; scp->cvol2 = scp->pvol2 = NAN; scp->cvol3 = scp->pvol3 = NAN; if (NEW(pd)) { pd->prevxo = pd->prevxo2 = pd->prevxo3 = NAN; pd->sep = *(p - 1) == '-' ? "-" : ""; pd->dlist = dlist_new(NULL, scpfree); dlist_insert_tail(pd->dlist, scp); table_insert(spots, spotname, pd); } else FREE(scp); } else dstr_free(spotname); } else { dlist_iter_t iter = dlist_iter_new(pd->dlist, DLIST_START_HEAD); dlist_node_t node; while ((node = dlist_next(iter))) { scp = (struct scp *)dlist_node_value(node); if (scp->strike > atof(strike) || fabs(scp->strike - atof(strike)) <= 0.000001) break; } dlist_iter_free(&iter); if (node == NULL || scp->strike > atof(strike)) { if (NEW(scp)) { scp->strike = atof(strike); scp->cvol = scp->pvol = NAN; scp->cvol2 = scp->pvol2 = NAN; scp->cvol3 = scp->pvol3 = NAN; } if (node == NULL) dlist_insert_tail(pd->dlist, scp); else dlist_insert(pd->dlist, node, scp, 0); } dstr_free(spotname); } dstr_free(strike); } var = var->next; } } cat = category_browse(cfg, cat); } } }
static int vxo_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); struct msgs *out = (struct msgs *)data2; dstr *fields = NULL; int nfield = 0; double vol, vol2, vol3, spot, strike, r, expiry; int sec, msec; dstr spotname; char *type; struct pd *pd; struct scp *scp; fields = dstr_split_len(msg->data, strlen(msg->data), ",", 1, &nfield); /* FIXME */ if (nfield != 19) { xcb_log(XCB_LOG_WARNING, "Message '%s' garbled", msg->data); goto end; } vol = !strcasecmp(fields[5], "nan") ? NAN : atof(fields[5]); vol2 = !strcasecmp(fields[7], "nan") ? NAN : atof(fields[7]); vol3 = !strcasecmp(fields[9], "nan") ? NAN : atof(fields[9]); if (isnan(vol) && isnan(vol2) && isnan(vol3)) goto end; sec = atoi(fields[1]); msec = atoi(fields[2]); spot = atof(fields[10]); spotname = dstr_new(fields[11]); type = fields[12]; strike = atof(fields[13]); r = atof(fields[14]); expiry = atof(fields[15]); table_lock(spots); if ((pd = table_get_value(spots, spotname)) == NULL) { /* can't happen */ if (NEW(scp) == NULL) { xcb_log(XCB_LOG_WARNING, "Error allocating memory for scp"); table_unlock(spots); goto end; } scp->strike = strike; if (!strcasecmp(type, "C")) { scp->cvol = vol; scp->pvol = NAN; scp->cvol2 = vol2; scp->pvol2 = NAN; scp->cvol3 = vol3; scp->pvol3 = NAN; } else { scp->cvol = NAN; scp->pvol = vol; scp->cvol2 = NAN; scp->pvol2 = vol2; scp->cvol3 = NAN; scp->pvol3 = vol3; } if (NEW(pd) == NULL) { xcb_log(XCB_LOG_WARNING, "Error allocating memory for pd"); FREE(scp); table_unlock(spots); goto end; } pd->prevxo = pd->prevxo2 = pd->prevxo3 = NAN; pd->sep = strchr(fields[3], '-') ? "-" : ""; pd->dlist = dlist_new(NULL, scpfree); dlist_insert_tail(pd->dlist, scp); table_insert(spots, spotname, pd); } else { dlist_iter_t iter = dlist_iter_new(pd->dlist, DLIST_START_HEAD); dlist_node_t node; while ((node = dlist_next(iter))) { scp = (struct scp *)dlist_node_value(node); if (scp->strike > strike || fabs(scp->strike - strike) <= 0.000001) break; } if (node && fabs(scp->strike - strike) <= 0.000001) { if (!strcasecmp(type, "C")) { scp->cvol = vol; scp->cvol2 = vol2; scp->cvol3 = vol3; } else { scp->pvol = vol; scp->pvol2 = vol2; scp->pvol3 = vol3; } } else { /* can't happen */ if (NEW(scp) == NULL) { xcb_log(XCB_LOG_WARNING, "Error allocating memory for scp"); table_unlock(spots); goto end; } scp->strike = strike; if (!strcasecmp(type, "C")) { scp->cvol = vol; scp->pvol = NAN; scp->cvol2 = vol2; scp->pvol2 = NAN; scp->cvol3 = vol3; scp->pvol3 = NAN; } else { scp->cvol = NAN; scp->pvol = vol; scp->cvol2 = NAN; scp->pvol2 = vol2; scp->cvol3 = NAN; scp->pvol3 = vol3; } if (node == NULL) dlist_insert_tail(pd->dlist, scp); else dlist_insert(pd->dlist, node, scp, 0); } dlist_iter_rewind_head(iter, pd->dlist); while ((node = dlist_next(iter))) { scp = (struct scp *)dlist_node_value(node); if (scp->strike > spot || fabs(scp->strike - spot) <= 0.000001) break; } dlist_iter_free(&iter); if (node && dlist_node_prev(node)) { struct scp *scp1 = (struct scp *)dlist_node_value(node); struct scp *scp2 = (struct scp *)dlist_node_value(dlist_node_prev(node)); double vxo = NAN, vxo2 = NAN, vxo3 = NAN; int flag1, flag2, flag3; if (!isnan(scp1->cvol) && !isnan(scp1->pvol) && !isnan(scp2->cvol) && !isnan(scp2->pvol)) vxo = ((scp1->cvol + scp1->pvol) / 2) * (spot - scp2->strike) / (scp1->strike - scp2->strike) + ((scp2->cvol + scp2->pvol) / 2) * (scp1->strike - spot) / (scp1->strike - scp2->strike); if (!isnan(scp1->cvol2) && !isnan(scp1->pvol2) && !isnan(scp2->cvol2) && !isnan(scp2->pvol2)) vxo2 = ((scp1->cvol2 + scp1->pvol2) / 2) * (spot - scp2->strike) / (scp1->strike - scp2->strike) + ((scp2->cvol2 + scp2->pvol2) / 2) * (scp1->strike - spot) / (scp1->strike - scp2->strike); if (!isnan(scp1->cvol3) && !isnan(scp1->pvol3) && !isnan(scp2->cvol3) && !isnan(scp2->pvol3)) vxo3 = ((scp1->cvol3 + scp1->pvol3) / 2) * (spot - scp2->strike) / (scp1->strike - scp2->strike) + ((scp2->cvol3 + scp2->pvol3) / 2) * (scp1->strike - spot) / (scp1->strike - scp2->strike); if ((flag1 = (isnan(pd->prevxo) && !isnan(vxo)) || (!isnan(pd->prevxo) && isnan(vxo)) || (!isnan(pd->prevxo) && !isnan(vxo) && fabs(pd->prevxo - vxo) > 0.000001) ? 1 : 0)) pd->prevxo = vxo; if ((flag2 = (isnan(pd->prevxo2) && !isnan(vxo2)) || (!isnan(pd->prevxo2) && isnan(vxo2)) || (!isnan(pd->prevxo2) && !isnan(vxo2) && fabs(pd->prevxo2 - vxo2) > 0.000001) ? 1 : 0)) pd->prevxo2 = vxo2; if ((flag3 = (isnan(pd->prevxo3) && !isnan(vxo3)) || (!isnan(pd->prevxo3) && isnan(vxo3)) || (!isnan(pd->prevxo3) && !isnan(vxo3) && fabs(pd->prevxo3 - vxo3) > 0.000001) ? 1 : 0)) pd->prevxo3 = vxo3; if (flag1 || flag2 || flag3) { char *res; if ((res = ALLOC(4096))) { time_t t = (time_t)sec; struct tm lt; char datestr[64]; int off; strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, 4096, "VXO,%s.%03d,%s|%f,%f,%f", datestr, msec, spotname, vxo, vxo2, vxo3); out2rmp(res); off = snprintf(res, 4096, "VXO,%d,%d,%s,", sec, msec, spotname); iter = dlist_iter_new(pd->dlist, DLIST_START_HEAD); while ((node = dlist_next(iter))) { scp = (struct scp *)dlist_node_value(node); off += snprintf(res + off, 4096 - off, "%.f,%f,%f,%f,", scp->strike, vxo, vxo2, vxo3); } dlist_iter_free(&iter); snprintf(res + off, 4096 - off, "%.2f,%f,%f,%s", spot, r, expiry, pd->sep); if (out2msgs(res, out) == -1) FREE(res); } } } dstr_free(spotname); } table_unlock(spots); end: dstr_free_tokens(fields, nfield); return 0; }
/* FIXME */ void s_command(client c) { dstr pkey, skey; int i; dlist_t dlist; struct kvd *kvd; if (dstr_length(c->argv[0]) == 1) { add_reply_error(c, "index can't be empty\r\n"); return; } pkey = dstr_new(c->argv[0] + 1); skey = dstr_new(pkey); if (c->argc > 1) for (i = 1; i < c->argc; ++i) { skey = dstr_cat(skey, ","); skey = dstr_cat(skey, c->argv[i]); } table_lock(cache); if ((dlist = table_get_value(cache, pkey))) { dlist_iter_t iter = dlist_iter_new(dlist, DLIST_START_HEAD); dlist_node_t node; /* FIXME: still has room to improve */ while ((node = dlist_next(iter))) { kvd = (struct kvd *)dlist_node_value(node); if (dstr_length(kvd->key) >= dstr_length(skey) && !memcmp(kvd->key, skey, dstr_length(skey))) { dstr *fields = NULL; int nfield = 0; dstr res, contracts = NULL; fields = dstr_split_len(kvd->key, dstr_length(kvd->key), ",", 1, &nfield); res = dstr_new(fields[0]); if (nfield > 1) { contracts = dstr_new(fields[1]); for (i = 2; i < nfield; ++i) { contracts = dstr_cat(contracts, ","); contracts = dstr_cat(contracts, fields[i]); } } dstr_free_tokens(fields, nfield); fields = NULL, nfield = 0; fields = dstr_split_len(kvd->u.value, dstr_length(kvd->u.value), ",", 1, &nfield); res = dstr_cat(res, ","); res = dstr_cat(res, fields[0]); if (contracts) { res = dstr_cat(res, ","); res = dstr_cat(res, contracts); } for (i = 1; i < nfield; ++i) { res = dstr_cat(res, ","); res = dstr_cat(res, fields[i]); } res = dstr_cat(res, "\r\n"); pthread_spin_lock(&c->lock); if (!(c->flags & CLIENT_CLOSE_ASAP)) { if (net_try_write(c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) { xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", c, strerror(errno)); if (++c->eagcount >= 3) { client_free_async(c); pthread_spin_unlock(&c->lock); dstr_free(contracts); dstr_free(res); dstr_free_tokens(fields, nfield); table_unlock(cache); dstr_free(skey); dstr_free(pkey); return; } } else if (c->eagcount) c->eagcount = 0; } pthread_spin_unlock(&c->lock); dstr_free(contracts); dstr_free(res); dstr_free_tokens(fields, nfield); } } dlist_iter_free(&iter); } table_unlock(cache); table_rwlock_wrlock(subscribers); if ((dlist = table_get_value(subscribers, pkey)) == NULL) { if (NEW(kvd)) { kvd->key = skey; kvd->u.dlist = dlist_new(NULL, NULL); dlist_insert_tail(kvd->u.dlist, c); dlist = dlist_new(cmpkvd, kdfree); dlist_insert_sort(dlist, kvd); table_insert(subscribers, pkey, dlist); } else { add_reply_error(c, "error allocating memory for kvd\r\n"); dstr_free(skey); dstr_free(pkey); } } else { if (NEW(kvd)) { dlist_node_t node; kvd->key = skey; kvd->u.dlist = dlist_new(NULL, NULL); if ((node = dlist_find(dlist, kvd)) == NULL) { dlist_insert_tail(kvd->u.dlist, c); dlist_insert_sort(dlist, kvd); } else { kdfree(kvd); kvd = (struct kvd *)dlist_node_value(node); if (dlist_find(kvd->u.dlist, c) == NULL) dlist_insert_tail(kvd->u.dlist, c); } } else { add_reply_error(c, "error allocating memory for kvd\r\n"); dstr_free(skey); } dstr_free(pkey); } table_rwlock_unlock(subscribers); }