/* FIXME */ void sall_command(client c) { dstr res = get_indices(); dstr *fields = NULL; int nfield = 0, i; RTRIM(res); fields = dstr_split_len(res, dstr_length(res), ",", 1, &nfield); for (i = 1; i < nfield; ++i) { dstr pkey = dstr_new(fields[i]); dstr skey = dstr_new(pkey); dlist_t dlist; struct kvd *kvd; 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); } dstr_free(res); //-------------------------------------------------------------------------------------------------------------------- // FIXME //-------------------------------------------------------------------------------------------------------------------- }
/**************************************************************** * Constructor */ void *strstr_new(t_symbol *sym, long argc, t_atom *argv) { t_strstr *x = NULL; x = (t_strstr *)object_alloc(strstr_class); if (x == NULL) { error("strstr: Allocation failed."); return NULL; } // Set inlets, outlets, and proxy x->inl_proxy_ind = 0; x->inl_proxy = proxy_new((t_object *)x, 1, &x->inl_proxy_ind); x->outl_int = intout((t_object *)x); // Set the left string buffer x->i_dstr1 = dstr_new(); // First argument: right string buffer x->i_dstr2 = dstr_new(); if ((argc >= 1) && (attr_args_offset((short)argc, argv) >= 1)) { x->i_dstr2 = str_cat_atom(x, x->i_dstr2, argv); } // Test the string buffers if (DSTR_IS_NULL(x->i_dstr1) || DSTR_IS_NULL(x->i_dstr2)) { object_error((t_object *)x, "Allocation error."); strstr_free(x); return NULL; } // Second argument: mode long mode = 0; if ((argc >= 2) && (attr_args_offset((short)argc, argv) >= 2)) { if ((atom_gettype(argv + 1) == A_LONG) && (atom_getlong(argv + 1) >= 0) && (atom_getlong(argv + 1) <= 1)) { mode = (long)atom_getlong(argv + 1); } else { object_error((t_object *)x, "Arg 2: Mode: 0 or 1 expected"); } } object_attr_setlong(x, gensym("mode"), mode); // Set the float precision object_attr_setlong(x, gensym("fprecision"), 6); // Set the remaining variables x->o_pos = -1; // Process the attributes attr_args_process(x, (short)argc, argv); return x; }
/* FIXME */ void u_command(client c) { dstr pkey, skey; dlist_t dlist; 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) { int i; for (i = 1; i < c->argc; ++i) { skey = dstr_cat(skey, ","); skey = dstr_cat(skey, c->argv[i]); } } table_rwlock_wrlock(subscribers); if ((dlist = table_get_value(subscribers, pkey))) { struct kvd *kvd; if (NEW(kvd)) { dlist_node_t node, node2; kvd->key = skey; if ((node = dlist_find(dlist, kvd))) { FREE(kvd); kvd = (struct kvd *)dlist_node_value(node); if ((node2 = dlist_find(kvd->u.dlist, c))) dlist_remove(kvd->u.dlist, node2); if (dlist_length(kvd->u.dlist) == 0) { dlist_remove(dlist, node); kdfree(kvd); } if (dlist_length(dlist) == 0) { table_remove(subscribers, pkey); dlist_free(&dlist); } } else FREE(kvd); } else add_reply_error(c, "error allocating memory for kvd"); } table_rwlock_unlock(subscribers); dstr_free(skey); dstr_free(pkey); add_reply_string(c, "\r\n", 2); }
/* FIXME */ int xcb_query(xcb_context_t c, const char *sid, const char *index, const char *pattern, struct tm *start, struct tm *end) { dstr s; char buf[128]; if (sid == NULL || index == NULL || start == NULL || end == NULL) { xcb_set_error(c, XCB_ERR_OTHER, "Session ID, index, start or end can't be empty"); return XCB_ERR; } s = dstr_new("Q"); s = dstr_cat(s, index); s = dstr_cat(s, ","); s = dstr_cat(s, sid); s = dstr_cat(s, ","); if (pattern) s = dstr_cat(s, pattern); s = dstr_cat(s, ","); strftime(buf, sizeof buf, "%F %T", start); s = dstr_cat(s, buf); s = dstr_cat(s, ","); strftime(buf, sizeof buf, "%F %T", end); s = dstr_cat(s, buf); s = dstr_cat(s, "\r\n"); if (net_try_write(c->fd, s, dstr_length(s), 10, NET_NONBLOCK) == -1) { xcb_set_error(c, XCB_ERR_IO, NULL); dstr_free(s); return XCB_ERR; } dstr_free(s); return XCB_OK; }
static void tcp_accept_handler(event_loop el, int fd, int mask, void *data) { char cip[128]; int cport, cfd; client c; NOT_USED(el); NOT_USED(mask); NOT_USED(data); if ((cfd = net_tcp_accept(fd, cip, &cport, neterr, sizeof neterr)) == -1) { xcb_log(XCB_LOG_WARNING, "Accepting client connection: %s", neterr); return; } if ((c = client_new(cfd, fd)) == NULL) { xcb_log(XCB_LOG_WARNING, "Error registering fd '%d' event for the new client: %s", cfd, strerror(errno)); close(cfd); } else { /* heartbeat */ dstr res = dstr_new("HEARTBEAT|"); dstr ip = getipv4(); xcb_log(XCB_LOG_NOTICE, "Accepted %s:%d, client '%p'", cip, cport, c); res = dstr_cat(res, ip); res = dstr_cat(res, "\r\n"); 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); dstr_free(ip); dstr_free(res); } }
/* FIXME */ void uall_command(client c) { dstr res = get_indices(); dstr *fields = NULL; int nfield = 0, i; RTRIM(res); fields = dstr_split_len(res, dstr_length(res), ",", 1, &nfield); for (i = 1; i < nfield; ++i) { dstr pkey = dstr_new(fields[i]); dstr skey = dstr_new(pkey); dlist_t dlist; table_rwlock_wrlock(subscribers); if ((dlist = table_get_value(subscribers, pkey))) { struct kvd *kvd; if (NEW(kvd)) { dlist_node_t node, node2; kvd->key = skey; if ((node = dlist_find(dlist, kvd))) { FREE(kvd); kvd = (struct kvd *)dlist_node_value(node); if ((node2 = dlist_find(kvd->u.dlist, c))) dlist_remove(kvd->u.dlist, node2); if (dlist_length(kvd->u.dlist) == 0) { dlist_remove(dlist, node); kdfree(kvd); } if (dlist_length(dlist) == 0) { table_remove(subscribers, pkey); dlist_free(&dlist); } } else FREE(kvd); } else add_reply_error(c, "error allocating memory for kvd"); } table_rwlock_unlock(subscribers); dstr_free(skey); dstr_free(pkey); } add_reply_string(c, "\r\n", 2); dstr_free(res); }
/* FIXME */ xcb_context_t xcb_connect(const char *addr, int port) { xcb_context_t c = xcb_context_init(); if (c == NULL) goto end; if (xcb_connect_tcp(c, addr, port) == XCB_ERR) goto end; info.c = c; info.ip = dstr_new(addr); info.port = port; if (pthread_create(&cthread, NULL, check_thread, &info) != 0) xcb_set_error_from_errno(c, XCB_ERR_OTHER, "pthread_create"); end: return c; }
/* FIXME */ int xcb_indices(xcb_context_t c, const char *sid) { dstr s; if (sid == NULL) { xcb_set_error(c, XCB_ERR_OTHER, "Session ID can't be empty"); return XCB_ERR; } s = dstr_new("INDICES,"); s = dstr_cat(s, sid); s = dstr_cat(s, "\r\n"); if (net_try_write(c->fd, s, dstr_length(s), 10, NET_NONBLOCK) == -1) { xcb_set_error(c, XCB_ERR_IO, NULL); dstr_free(s); return XCB_ERR; } dstr_free(s); return XCB_OK; }
/* FIXME */ int xcb_index(xcb_context_t c, const char *index) { dstr s; if (index == NULL) { xcb_set_error(c, XCB_ERR_OTHER, "Index can't be empty"); return XCB_ERR; } s = dstr_new("INDEX,"); s = dstr_cat(s, index); s = dstr_cat(s, "\r\n"); if (net_try_write(c->fd, s, dstr_length(s), 10, NET_NONBLOCK) == -1) { xcb_set_error(c, XCB_ERR_IO, NULL); dstr_free(s); return XCB_ERR; } dstr_free(s); return XCB_OK; }
/* FIXME */ void qc_command(client c) { char buf[64]; dstr rid; struct crss *crss; snprintf(buf, sizeof buf, "%p,", c); rid = dstr_new(buf); rid = dstr_cat(rid, c->argv[1]); if (rids == NULL) rids = table_new(cmpstr, hashmurmur2, kfree, NULL); table_lock(rids); if ((crss = table_get_value(rids, rid))) { crss->cancel = 1; xcb_log(XCB_LOG_DEBUG, "Query with rid '%s' got cancelled", c->argv[1]); } table_unlock(rids); add_reply_string(c, "\r\n", 2); dstr_free(rid); }
int main(int argc, char **argv) { int opt, count = 1; pthread_t thread; /* FIXME */ ip = dstr_new("127.0.0.1"); port = 33330; while ((opt = getopt(argc, argv, "h:p:xt?")) != -1) switch (opt) { case 'h': dstr_free(ip); ip = dstr_new(optarg); count += 2; break; case 'p': port = atoi(optarg); count += 2; break; case 'x': execute = 1; count += 1; break; case 't': timestamp = 1; count += 1; break; case '?': default: usage(); } if ((tcpsock = net_tcp_nonblock_connect(ip, port, neterr, sizeof neterr)) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, neterr); exit(1); } if (errno == EINPROGRESS) { struct pollfd wfd[1]; int res, err = 0; socklen_t errlen = sizeof err; wfd[0].fd = tcpsock; wfd[0].events = POLLOUT; /* wait for 5 seconds */ if ((res = poll(wfd, 1, 5000)) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } else if (res == 0) { errno = ETIMEDOUT; fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } if (getsockopt(tcpsock, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } if (err) { errno = err; fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } } if (execute && pipe(proceed_pipe) != 0) { fprintf(stderr, "Error creating pipe: %s\n", strerror(errno)); exit(1); } if (execute) { argc -= count; argv += count; if (argc > 0) { dstr cmd; int i; struct pollfd rfd[1]; if (pthread_create(&thread, NULL, recv_thread, NULL) != 0) { fprintf(stderr, "Error initializing receiver thread\n"); exit(1); } cmd = dstr_new(argv[0]); for (i = 1; i < argc; ++i) { cmd = dstr_cat(cmd, " "); cmd = dstr_cat(cmd, argv[i]); } cmd = dstr_cat(cmd, "\r\n"); net_try_write(tcpsock, cmd, dstr_length(cmd), 100, NET_NONBLOCK); /* dstr_free(cmd); */ rfd[0].fd = proceed_pipe[0]; rfd[0].events = POLLIN; if (poll(rfd, 1, -1) == -1) { fprintf(stderr, "Error polling: %s\n", strerror(errno)); exit(1); } } } else { fprintf(stdout, "XCUBE CLI, Copyright (c) 2013-2015, " "Dalian Futures Information Technology Co., Ltd.\n"); fprintf(stdout, "Type 'help' or '?' for help.\n"); init_readline(); stifle_history(100); if (pthread_create(&thread, NULL, recv_thread, NULL) != 0) { fprintf(stderr, "Error initializing receiver thread\n"); exit(1); } while (loop) { char *line; line = readline(prompt); if (rl_inited == 0) rl_inited = 1; if (line == NULL) continue; LTRIM(line); RTRIM(line); if (*line) { add_history(line); if (tcpsock == -1) execute_line(line); else { net_try_write(tcpsock, line, strlen(line), 100, NET_NONBLOCK); net_try_write(tcpsock, "\r\n", 2, 100, NET_NONBLOCK); if (!strncasecmp(line, "quit", 4)) com_quit(NULL); } } FREE(line); } } 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; }
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); //------------------------------------------------------------------------ dstr pre = dstr_new(pkey); dstr rest = dstr_new(""); //------------------------------------------------------------------------ if (c->argc > 1) for (i = 1; i < c->argc; ++i) { skey = dstr_cat(skey, ","); skey = dstr_cat(skey, c->argv[i]); //------------------------------------------------------------------------ rest = dstr_cat(rest,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); */ //-------------------------------------------------------------------------------------------------------------------- // table_rwlock_wrlock(subscribers_radix); radix_block_insert(pre, ",", subscribers_radix->head); radix_insert(rest, radix_match(pre, subscribers_radix->head, subscribers_radix->head)); pre = dstr_cat(pre,rest); insert_value(pre, c, subscribers_radix->head); dstr_free(pre); dstr_free(rest); // table_rwlock_unlock(subscribers_radix); //--------------------------------------------------------------------------------------------------- }
/* FIXME */ void q_command(client c) { struct tm tm; char *end; char buf[64]; dstr rid; struct crss *crss; if (!persistence) { add_reply_error(c, "database not open\r\n"); return; } if (dstr_length(c->argv[0]) == 1) { add_reply_error(c, "index can't be empty\r\n"); return; } if ((end = strptime(c->argv[3], "%F %T", &tm)) && *end == '\0') c->argv[3] = dstr_cat(c->argv[3], ".000"); else if ((end = strptime(c->argv[3], "%F %R", &tm)) && *end == '\0') c->argv[3] = dstr_cat(c->argv[3], ":00.000"); else { add_reply_error(c, "invalid time format, " "please use 'YYYY-mm-dd HH:MM:SS' or 'YYYY-mm-dd HH:MM'.\r\n"); return; } if ((end = strptime(c->argv[4], "%F %T", &tm)) && *end == '\0') c->argv[4] = dstr_cat(c->argv[4], ".999"); else if ((end = strptime(c->argv[4], "%F %R", &tm)) && *end == '\0') c->argv[4] = dstr_cat(c->argv[4], ":59.999"); else { add_reply_error(c, "invalid time format, " "please use 'YYYY-mm-dd HH:MM:SS' or 'YYYY-mm-dd HH:MM'.\r\n"); return; } snprintf(buf, sizeof buf, "%p,", c); rid = dstr_new(buf); rid = dstr_cat(rid, c->argv[1]); if (rids == NULL) rids = table_new(cmpstr, hashmurmur2, kfree, NULL); table_lock(rids); if ((crss = table_get_value(rids, rid))) { add_reply_error_format(c, "query with rid '%s' already exists\r\n", c->argv[1]); dstr_free(rid); } else if (NEW(crss)) { pthread_t thread; crss->c = c; crss->rid = dstr_new(c->argv[1]); crss->match = dstr_new(c->argv[2]); crss->start = dstr_new(c->argv[0] + 1); crss->start = dstr_cat(crss->start, ","); crss->start = dstr_cat(crss->start, c->argv[3]); crss->stop = dstr_new(c->argv[0] + 1); crss->stop = dstr_cat(crss->stop, ","); crss->stop = dstr_cat(crss->stop, c->argv[4]); crss->cancel = 0; if (pthread_create(&thread, NULL, q_thread, crss) != 0) { add_reply_error(c, strerror(errno)); add_reply_string(c, "\r\n", 2); dstr_free(crss->rid); dstr_free(crss->match); dstr_free(crss->start); dstr_free(crss->stop); FREE(crss); dstr_free(rid); } else { client_incr(crss->c); table_insert(rids, rid, crss); } } else { add_reply_error(c, "error allocating memory for crss\r\n"); dstr_free(rid); } table_unlock(rids); }
/* FIXME */ static void *q_thread(void *data) { struct crss *crss = (struct crss *)data; char buf[64]; dstr rid, res = NULL; db_iterator_t *it; const char *key, *value; size_t klen, vlen; snprintf(buf, sizeof buf, "%p,", crss->c); rid = dstr_new(buf); rid = dstr_cat(rid, crss->rid); it = db_iterator_create(db, db_ro); db_iterator_seek(it, crss->start, dstr_length(crss->start)); /* seek failed */ if (!db_iterator_valid(it)) { res = dstr_new(crss->rid); res = dstr_cat(res, ",1\r\n\r\n"); pthread_spin_lock(&crss->c->lock); if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno)); pthread_spin_unlock(&crss->c->lock); goto end; } key = db_iterator_key(it, &klen); while (memcmp(key, crss->stop, dstr_length(crss->stop)) <= 0) { if (crss->cancel) break; if (!strcmp(crss->match, "") || strstr(key, crss->match)) { value = db_iterator_value(it, &vlen); res = dstr_new(crss->rid); res = dstr_cat(res, ",0,"); res = dstr_cat_len(res, key, klen); res = dstr_cat(res, ","); res = dstr_cat_len(res, value, vlen); res = dstr_cat(res, "\r\n"); pthread_spin_lock(&crss->c->lock); if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) { xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno)); pthread_spin_unlock(&crss->c->lock); goto end; } pthread_spin_unlock(&crss->c->lock); dstr_free(res); } db_iterator_next(it); if (!db_iterator_valid(it) || crss->cancel) break; key = db_iterator_key(it, &klen); } res = dstr_new(crss->rid); res = dstr_cat(res, ",1\r\n\r\n"); pthread_spin_lock(&crss->c->lock); if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno)); pthread_spin_unlock(&crss->c->lock); end: db_iterator_destroy(&it); dstr_free(res); table_lock(rids); table_remove(rids, rid); table_unlock(rids); dstr_free(rid); client_decr(crss->c); dstr_free(crss->rid); dstr_free(crss->match); dstr_free(crss->start); dstr_free(crss->stop); FREE(crss); return NULL; }
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 int mm_impvbaw_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); dstr *fields = NULL; int nfield = 0; time_t t; dstr spotname; double vol; NOT_USED(data2); 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; } t = (time_t)atoi(fields[1]); spotname = dstr_new(fields[11]); vol = atof(fields[5]); if (!isnan(vol)) { struct mm *mm; int flag = 0; table_lock(contracts); if ((mm = table_get_value(contracts, spotname)) == NULL) { if (NEW(mm)) { mm->min = mm->max = vol; flag = 1; table_insert(contracts, spotname, mm); } else xcb_log(XCB_LOG_WARNING, "Error allocating memory for mm"); } else { if (mm->min > vol) { mm->min = vol; flag = 1; } else if (mm->max < vol) { mm->max = vol; flag = 1; } dstr_free(spotname); } if (mm && flag) { struct tm lt; char datestr[64], res[512]; localtime_r(&t, <); lt.tm_hour = lt.tm_min = lt.tm_sec = 0; strftime(datestr, sizeof datestr, "%F %T", <); snprintf(res, sizeof res, "MM_IMPVBAW,%s.000,%s|%f,%f", datestr, fields[11], mm->min, mm->max); out2rmp(res); } table_unlock(contracts); } end: dstr_free_tokens(fields, nfield); return 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 impvbaw_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); Quote *quote = (Quote *)msg->data; struct msgs *out = (struct msgs *)data2; dstr contract; float last; char *p; table_node_t node; contract = dstr_new(quote->thyquote.m_cHYDM); if (!strcmp(contract, "") || (fabs(quote->thyquote.m_dZXJ) <= 0.000001 && fabs(quote->thyquote.m_dMRJG1) <= 0.000001 && fabs(quote->thyquote.m_dMCJG1) <= 0.000001)) { xcb_log(XCB_LOG_WARNING, "Invalid quote: '%d,%d,%s,%.2f,%.2f,%.2f'", quote->thyquote.m_nTime, quote->m_nMSec, contract, quote->thyquote.m_dZXJ, quote->thyquote.m_dMRJG1, quote->thyquote.m_dMCJG1); goto end; } /* FIXME */ if (!strncasecmp(contract, "IO", 2) || !strncasecmp(contract, "HO", 2) || !strncasecmp(contract, "00", 2) || !strncasecmp(contract, "60", 2)) goto end; last = quote->thyquote.m_dZXJ; if ((p = strrchr(contract, 'C')) == NULL) p = strrchr(contract, 'P'); /* FIXME: option quote */ if (p && p != contract && p != contract + dstr_length(contract) - 1 && ((*(p - 1) == '-' && *(p + 1) == '-') || (isdigit(*(p - 1)) && isdigit(*(p + 1))))) { dstr spotname, type, strike; float spot; struct prices *prices; double expiry, vol, vol2, vol3; struct tm lt; char *res; spotname = *(p - 1) == '-' ? dstr_new_len(contract, p - contract - 1) : dstr_new_len(contract, p - contract); type = dstr_new_len(p, 1); strike = *(p + 1) == '-' ? dstr_new_len(p + 2, contract + dstr_length(contract) - p - 2) : dstr_new_len(p + 1, contract + dstr_length(contract) - p - 1); table_rwlock_rdlock(spots); if ((node = table_find(spots, spotname)) == NULL) { table_rwlock_unlock(spots); dstr_free(strike); dstr_free(type); dstr_free(spotname); goto end; } spot = table_node_float(node); table_rwlock_unlock(spots); if (fabs(spot) <= 0.000001) { xcb_log(XCB_LOG_WARNING, "The price of spot '%s' be zero", spotname); dstr_free(strike); dstr_free(type); dstr_free(spotname); goto end; } table_lock(optns); if ((node = table_find(optns, contract)) == NULL) { if (NEW(prices)) { prices->prelast = last; prices->prebid1 = quote->thyquote.m_dMRJG1; prices->preask1 = quote->thyquote.m_dMCJG1; prices->prespot = spot; table_insert(optns, dstr_new(contract), prices); } else xcb_log(XCB_LOG_WARNING, "Error allocating memory for prices"); } else { prices = (struct prices *)table_node_value(node); if (fabs(prices->prelast - last) <= 0.000001 && fabs(prices->prebid1 - quote->thyquote.m_dMRJG1) <= 0.000001 && fabs(prices->preask1 - quote->thyquote.m_dMCJG1) <= 0.000001 && fabs(prices->prespot - spot) <= 0.000001) { table_unlock(optns); dstr_free(strike); dstr_free(type); dstr_free(spotname); goto end; } else { prices->prelast = last; prices->prebid1 = quote->thyquote.m_dMRJG1; prices->preask1 = quote->thyquote.m_dMCJG1; prices->prespot = spot; } } table_unlock(optns); if ((node = table_find(expiries, contract))) expiry = table_node_double(node); else { char *month; struct timeval tv; int diff; xcb_log(XCB_LOG_WARNING, "No exact expiry date for '%s'", contract); month = spotname + dstr_length(spotname) - 2; gettimeofday(&tv, NULL); if ((diff = atoi(month) - localtime_r(&tv.tv_sec, <)->tm_mon - 1) < 0) diff += 12; if (diff == 0) diff = 1; expiry = diff / 12.0; } /* FIXME: last price */ if (fabs(last) <= 0.000001) vol = NAN; else vol = impv_baw(spot, atof(strike), r, r, expiry, last, !strcasecmp(type, "C") ? AMER_CALL : AMER_PUT); /* FIXME: bid price 1 */ if (fabs(quote->thyquote.m_dMRJG1) <= 0.000001) vol2 = NAN; else if (fabs(quote->thyquote.m_dMRJG1 - last) <= 0.000001) vol2 = vol; else vol2 = impv_baw(spot, atof(strike), r, r, expiry, quote->thyquote.m_dMRJG1, !strcasecmp(type, "C") ? AMER_CALL : AMER_PUT); /* FIXME: ask price 1 */ if (fabs(quote->thyquote.m_dMCJG1) <= 0.000001) vol3 = NAN; else if (fabs(quote->thyquote.m_dMCJG1 - last) <= 0.000001) vol3 = vol; else vol3 = impv_baw(spot, atof(strike), r, r, expiry, quote->thyquote.m_dMCJG1, !strcasecmp(type, "C") ? AMER_CALL : AMER_PUT); if ((res = ALLOC(512))) { time_t t = (time_t)quote->thyquote.m_nTime; char datestr[64]; strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, 512, "IMPVBAW,%s.%03d,%s|%.2f,%f,%.2f,%f,%.2f,%f,%.2f", datestr, quote->m_nMSec, contract, last, vol, quote->thyquote.m_dMRJG1, vol2, quote->thyquote.m_dMCJG1, vol3, spot); out2rmp(res); snprintf(res, 512, "IMPVBAW,%d,%d,%s,%.2f,%f,%.2f,%f,%.2f,%f,%.2f,%s,%s,%s,%f,%f,%d,0,0", quote->thyquote.m_nTime, quote->m_nMSec, contract, last, vol, quote->thyquote.m_dMRJG1, vol2, quote->thyquote.m_dMCJG1, vol3, spot, spotname, type, strike, r, expiry, quote->thyquote.m_nCJSL); if (out2msgs(res, out) == -1) FREE(res); } else xcb_log(XCB_LOG_WARNING, "Error allocating memory for result"); dstr_free(strike); dstr_free(type); dstr_free(spotname); /* future quote */ } else { table_rwlock_wrlock(spots); if ((node = table_find(spots, contract)) == NULL) { if ((node = table_insert_raw(spots, contract))) table_set_float(node, last); } else { table_set_float(node, last); dstr_free(contract); } table_rwlock_unlock(spots); return 0; } end: dstr_free(contract); return 0; }
int main(int argc, char **argv) { int opt, i = 1, fd, sock; struct stat sb; char *addr, *p, *q; char neterr[256]; int pfd[2]; /* FIXME */ ip = dstr_new("127.0.0.1"); port = 33330; while ((opt = getopt(argc, argv, "h:p:?")) != -1) switch (opt) { case 'h': dstr_free(ip); ip = dstr_new(optarg); i += 2; break; case 'p': port = atoi(optarg); i += 2; break; case '?': default: usage(); } if ((fd = open(argv[i], O_RDONLY)) == -1) { fprintf(stderr, "Error opening file: %s\n", strerror(errno)); exit(1); } fstat(fd, &sb); if ((addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) { fprintf(stderr, "Error mmaping file: %s\n", strerror(errno)); exit(1); } close(fd); if ((sock = net_udp_nonblock_connect(ip, port, neterr, sizeof neterr)) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, neterr); exit(1); } if (pipe(pfd) != 0) { fprintf(stderr, "Error creating pipe: %s\n", strerror(errno)); exit(1); } p = addr; q = memchr(p, '\n', sb.st_size); while (q) { int len = PAGEALIGN(q - p + 1); char *line; if ((line = POSIXALIGN(sysconf(_SC_PAGESIZE), len))) { struct iovec iov; memset(line, '\0', len); strncpy(line, p, q - p); iov.iov_base = line; iov.iov_len = len; /* zero copy */ if (vmsplice(pfd[1], &iov, 1, SPLICE_F_GIFT) == -1) { fprintf(stderr, "Error vmsplicing: %s\n", strerror(errno)); exit(1); } again: if (splice(pfd[0], NULL, sock, NULL, len, SPLICE_F_MOVE) == -1) { if (errno == EAGAIN) goto again; else { fprintf(stderr, "Error splicing: %s\n", strerror(errno)); exit(1); } } FREE(line); } else fprintf(stderr, "Error allocating memory for line\n"); p = q + 1; q = memchr(p, '\n', sb.st_size - (q - addr)); } close(pfd[0]); close(pfd[1]); close(sock); munmap(addr, sb.st_size); return 0; }
static void *recv_thread(void *data) { NOT_USED(data); while (loop) { struct pollfd rfd[1]; char buf[256]; int nread; rfd[0].fd = tcpsock; rfd[0].events = POLLIN; if (poll(rfd, 1, -1) == -1) { if (execute) { fprintf(stderr, "Reading from server: %s\n", strerror(errno)); exit(1); } else { snprintf(buf, sizeof buf, "Reading from server: %s", strerror(errno)); CLIPRINT(buf); break; } } if ((nread = read(tcpsock, inbuf + inpos, sizeof inbuf - inpos)) == -1) { if (errno == EAGAIN || errno == EINTR) nread = 0; else { if (execute) { fprintf(stderr, "Reading from server: %s\n", strerror(errno)); exit(1); } else { snprintf(buf, sizeof buf, "Reading from server: %s", strerror(errno)); CLIPRINT(buf); break; } } } else if (nread == 0) { if (execute) { fprintf(stderr, "Server closed connection\n"); exit(1); } else { snprintf(buf, sizeof buf, "Server closed connection"); CLIPRINT(buf); break; } } if (nread) inpos += nread; else continue; inbuf[inpos] = '\0'; while (inpos > 0) { char *newline; size_t len; if ((newline = strstr(inbuf, "\r\n")) == NULL) { if (inpos == sizeof inbuf - 1) { if (execute) { fprintf(stderr, "Server error: too big reply\n"); exit(1); } else { snprintf(buf, sizeof buf, "Server error: too big reply"); CLIPRINT(buf); inpos = 0; } } break; } if ((len = newline - inbuf) == 0) { const char one = '1'; if (execute && write(proceed_pipe[1], &one, sizeof(one)) == -1) { fprintf(stderr, "Error writing: %s", strerror(errno)); exit(1); } } else { /* FIXME */ *newline = '\0'; if (timestamp) { struct timeval tv; char datestr[64]; int off; dstr res; gettimeofday(&tv, NULL); off = strftime(datestr, sizeof datestr, "[%b %e %T.", localtime(&tv.tv_sec)); snprintf(datestr + off, sizeof datestr - off, "%06d]", (int)tv.tv_usec); res = dstr_new(datestr); res = dstr_cat(res, inbuf); if (execute) { if (strncasecmp(inbuf, "HEARTBEAT", 9) && strncasecmp(inbuf, "INDICES", 7)) fprintf(stdout, "%s\n", res); } else CLIPRINT(res); dstr_free(res); } else { if (execute) { if (strncasecmp(inbuf, "HEARTBEAT", 9) && strncasecmp(inbuf, "INDICES", 7)) fprintf(stdout, "%s\n", inbuf); } else CLIPRINT(inbuf); } } memmove(inbuf, inbuf + len + 2, sizeof inbuf - len - 2); inpos -= len + 2; } } close(tcpsock); tcpsock = -1; return NULL; }