static int md_snapshot(struct fast_book *book, struct fast_message *msg) { struct price_level *levels; struct fast_decimal price; struct fast_field *field; struct price_level level; char type; i64 size; u32 ind; field = fast_get_field(msg, "MDEntryType"); if (!field || field_state_empty(field)) goto fail; type = field->string_value[0]; if (type == '0') { levels = book->ob.bids; } else if (type == '1') { levels = book->ob.asks; } else if (type == 'J') { book_add_flags(book, FAST_BOOK_EMPTY); goto exit; } else { goto fail; } field = fast_get_field(msg, "MDPriceLevel"); if (!field || field_state_empty(field)) goto fail; ind = field->uint_value - 1; field = fast_get_field(msg, "MDEntrySize"); if (!field || field_state_empty(field)) goto fail; size = field->int_value; field = fast_get_field(msg, "MDEntryPx"); if (!field || field_state_empty(field)) goto fail; price = field->decimal_value; if (price_align(&price, &book->tick)) goto fail; level.price = price.mnt; level.size = size; if (set_price_level(levels, book->ob.depth, &level, ind)) goto fail; exit: return 0; fail: return -1; }
static int apply_snapshot(struct fast_book_set *set, struct fast_book *dst, struct fast_message *msg) { struct fast_sequence *seq; struct fast_field *field; struct fast_message *md; struct fast_book *book; int i; field = fast_get_field(msg, "SecurityID"); if (!field || field_state_empty(field)) goto fail; book = fast_book_find(set, field->uint_value); if (!book || book_has_flags(book, FAST_BOOK_ACTIVE)) goto done; if (dst && dst->secid != book->secid) goto done; field = fast_get_field(msg, "MDEntries"); if (!field || field_state_empty(field)) goto fail; seq = field->ptr_value; if (field_state_empty(&seq->length)) goto fail; field = fast_get_field(msg, "RptSeq"); if (!field || field_state_empty(field)) goto fail; book->rptseq = field->uint_value; book_clear_flags(book, FAST_BOOK_EMPTY); book_add_mask(set, book); for (i = 1; i <= seq->length.uint_value; i++) { md = seq->elements + i; if (md_snapshot(book, md)) goto fail; } if (!fast_book_is_valid(book)) { if (!book_has_flags(book, FAST_BOOK_EMPTY)) goto fail; } else { book_add_flags(book, FAST_BOOK_ACTIVE); } done: return 0; fail: return -1; }
void BytecodeClosure::aload_0_fast_get_field_n(int bytecode JVM_TRAPS) { load_local(T_OBJECT, 0 JVM_CHECK); const static jbyte types[4] = {T_OBJECT, T_INT, T_OBJECT, T_INT}; const static jbyte sizes[4] = {4, 4, 8, 8}; const int index = bytecode - Bytecodes::_aload_0_fast_agetfield_4; BasicType field_type = (BasicType)types[index]; int offset = (int)sizes[index]; fast_get_field(field_type, offset JVM_CHECK); }
static int recv_snapshot(struct fast_book_set *set, struct fast_feed *feed, struct fast_message **next) { struct fast_message *msg; struct fast_field *field; enum fix_msg_type type; *next = NULL; msg = fast_feed_recv(feed, 0); if (!msg) { goto done; } else if (fast_msg_has_flags(msg, FAST_MSG_FLAGS_RESET)) { fast_session_reset(feed->session); goto done; } field = fast_get_field(msg, "MessageType"); if (!field || field_state_empty(field)) goto fail; type = fix_msg_type_parse(field->string_value, 0x00); switch (type) { case FIX_MSG_TYPE_SESSION_STATUS: break; case FIX_MSG_TYPE_SEQUENCE_RESET: break; case FIX_MSG_TYPE_HEARTBEAT: break; case FIX_MSG_TYPE_SNAPSHOT_REFRESH: *next = msg; break; default: goto fail; } done: return 0; fail: return -1; }
static int fast_books_join(struct fast_book_set *set, struct fast_book *book) { struct fast_message *inc_buf = NULL; struct fast_message *tmp_buf; struct fast_field *field; struct fast_message *msg; unsigned long size = 32; unsigned long pos = 0; u64 last_msg_seq_num; u64 msg_seq_num = 0; unsigned long i; if (fast_feed_open(set->snp_feeds)) goto fail; inc_buf = calloc(size, sizeof(struct fast_message)); if (!inc_buf) goto fail; book_clear_flags(book, FAST_BOOK_ACTIVE); while (!book_has_flags(book, FAST_BOOK_ACTIVE)) { if (next_increment(set, &msg)) goto fail; if (!msg) continue; if (apply_increment(set, NULL, msg)) goto fail; if (pos >= size) { size *= 2; tmp_buf = realloc(inc_buf, size * sizeof(struct fast_message)); if (!tmp_buf) goto fail; inc_buf = tmp_buf; } if (fast_message_copy(inc_buf + pos, msg)) { goto fail; } else pos++; if (!msg_seq_num) { field = fast_get_field(msg, "MsgSeqNum"); if (!field || field_state_empty(field)) goto fail; msg_seq_num = field->uint_value; } if (next_snapshot(set, &msg)) goto fail; if (!msg) continue; field = fast_get_field(msg, "LastMsgSeqNumProcessed"); if (!field || field_state_empty(field)) goto fail; last_msg_seq_num = field->uint_value; if (last_msg_seq_num < msg_seq_num) continue; if (apply_snapshot(set, book, msg)) goto fail; } if (!pos) goto fail; for (i = 0; i < pos; i++) { msg = inc_buf + i; field = fast_get_field(msg, "MsgSeqNum"); if (!field || field_state_empty(field)) goto fail; msg_seq_num = field->uint_value; if (msg_seq_num <= last_msg_seq_num) continue; if (apply_increment(set, book, msg)) goto fail; } if (fast_feed_close(set->snp_feeds)) goto fail; fast_message_free(inc_buf, pos); return 0; fail: fast_feed_close(set->snp_feeds); fast_message_free(inc_buf, pos); return -1; }
static int recv_increment(struct fast_book_set *set, struct fast_feed *feed, struct fast_message **next) { struct fast_message *msg; struct fast_field *field; enum fix_msg_type type; u64 msg_num; *next = NULL; if (feed->recv_num > set->inc_msg_num) goto done; msg = fast_feed_recv(feed, 0); if (!msg) { goto done; } else if (fast_msg_has_flags(msg, FAST_MSG_FLAGS_RESET)) { fast_session_reset(feed->session); goto done; } field = fast_get_field(msg, "MsgSeqNum"); if (!field || field_state_empty(field)) goto fail; msg_num = field->uint_value; feed->recv_num = msg_num; if (!set->inc_msg_num) { set->inc_msg_num = msg_num; } else if (set->inc_msg_num + 1 == msg_num) { set->inc_msg_num++; if (set->inc_gap_mode) set->inc_gap_mode = false; } else if (set->inc_msg_num < msg_num) { set->inc_gap_mode = true; goto done; } else goto done; field = fast_get_field(msg, "MessageType"); if (!field || field_state_empty(field)) goto fail; type = fix_msg_type_parse(field->string_value, 0x00); switch (type) { case FIX_MSG_TYPE_SESSION_STATUS: break; case FIX_MSG_TYPE_SEQUENCE_RESET: break; case FIX_MSG_TYPE_HEARTBEAT: break; case FIX_MSG_TYPE_INCREMENT_REFRESH: *next = msg; break; default: goto fail; } done: return 0; fail: return -1; }
void BytecodeClosure::aload_0_fast_get_field_1(BasicType field_type JVM_TRAPS){ load_local(T_OBJECT, 0 JVM_CHECK); int offset = method()->get_ubyte(_bci+1) * BytesPerWord; fast_get_field(field_type, offset JVM_CHECK); }
static int fast_books_join(struct fast_book_set *set, struct fast_book *book) { struct fast_message *inc_msg = NULL; struct fast_message *snp_msg = NULL; bool snp_received = false; struct fast_field *field; struct fast_book *sbook; struct ob_level *level; struct ob_order order; u64 last_msg_seq_num; u64 msg_num_init = 0; u64 msg_num_cur = 0; GList *list; if (fast_feed_open(set->snp_feeds)) goto fail; book_clear_flags(book, FAST_BOOK_ACTIVE); book_add_flags(book, FAST_BOOK_JOIN); while (!book_has_flags(book, FAST_BOOK_ACTIVE)) { if (next_increment(set, &inc_msg)) goto fail; if (inc_msg) { if (apply_increment(set, NULL, inc_msg)) goto fail; field = fast_get_field(inc_msg, "MsgSeqNum"); if (!field || field_state_empty(field)) goto fail; msg_num_cur = field->uint_value; if (!msg_num_init) msg_num_init = msg_num_cur; } if (!snp_received) { if (next_snapshot(set, &snp_msg)) goto fail; } if (snp_msg) { field = fast_get_field(snp_msg, "SecurityID"); if (field) { if (field_state_empty(field)) goto fail; sbook = fast_book_by_id(set, field->uint_value); if (!sbook || book->secid != sbook->secid) continue; } else { field = fast_get_field(snp_msg, "Symbol"); if (!field || field_state_empty(field)) goto fail; sbook = fast_book_by_symbol(set, field->string_value); if (!sbook || strcmp(sbook->symbol, book->symbol)) continue; } field = fast_get_field(snp_msg, "LastMsgSeqNumProcessed"); if (!field || field_state_empty(field)) goto fail; last_msg_seq_num = field->uint_value; if (!msg_num_init) continue; if (last_msg_seq_num < msg_num_init) continue; snp_received = true; if (last_msg_seq_num > msg_num_cur) continue; if (apply_snapshot(set, book, snp_msg)) goto fail; if (book_has_flags(book, FAST_BOOK_EMPTY)) snp_received = false; } } order.buy = false; list = g_list_first(book->ob.glasks); while (list) { level = g_list_nth_data(list, 0); list = g_list_next(list); if (!level->size) { order.price = level->price; if (ob_level_delete(&book->ob, &order)) goto fail; } } order.buy = true; list = g_list_first(book->ob.glbids); while (list) { level = g_list_nth_data(list, 0); list = g_list_next(list); if (!level->size) { order.price = level->price; if (ob_level_delete(&book->ob, &order)) goto fail; } } book_clear_flags(book, FAST_BOOK_JOIN); if (fast_feed_close(set->snp_feeds)) goto fail; return 0; fail: fast_feed_close(set->snp_feeds); return -1; }
static int md_increment(struct fast_book *book, struct fast_message *msg) { struct fast_decimal price; struct fast_field *field; struct ob_order order; char type; i64 size; field = fast_get_field(msg, "MDEntryType"); if (!field || field_state_empty(field)) goto fail; type = field->string_value[0]; if (type == '0') { order.buy = true; } else if (type == '1') { order.buy = false; } else if (type == 'J') { book_add_flags(book, FAST_BOOK_EMPTY); goto exit; } else { goto fail; } field = fast_get_field(msg, "MDEntrySize"); if (!field || field_state_empty(field)) goto fail; switch (field->type) { case FAST_TYPE_INT: size = field->int_value; break; case FAST_TYPE_DECIMAL: if (decimal_to_int(&field->decimal_value, &size)) goto fail; break; case FAST_TYPE_UINT: case FAST_TYPE_STRING: case FAST_TYPE_VECTOR: case FAST_TYPE_SEQUENCE: default: goto fail; } field = fast_get_field(msg, "MDEntryPx"); if (!field || field_state_empty(field)) goto fail; price = field->decimal_value; if (price_align(&price, &book->tick)) goto fail; order.seq_num = book->rptseq; order.price = price.mnt; order.size = size; field = fast_get_field(msg, "MDUpdateAction"); if (!field || field_state_empty(field)) goto fail; if (field->uint_value == 0) { if (ob_level_modify(&book->ob, &order)) goto fail; } else if (field->uint_value == 1) { if (ob_level_modify(&book->ob, &order)) goto fail; } else if (field->uint_value == 2) { if (book_has_flags(book, FAST_BOOK_ACTIVE)) { if (ob_level_delete(&book->ob, &order)) goto fail; } else { order.size = 0; if (ob_level_modify(&book->ob, &order)) goto fail; } } else { goto fail; } exit: return 0; fail: return -1; }
static int apply_snapshot(struct fast_book_set *set, struct fast_book *dst, struct fast_message *msg) { struct fast_sequence *seq; struct fast_field *field; struct fast_message *md; struct fast_book *book; int i; field = fast_get_field(msg, "SecurityID"); if (field) { if (field_state_empty(field)) goto fail; book = fast_book_by_id(set, field->uint_value); if (!book || book_has_flags(book, FAST_BOOK_ACTIVE)) goto done; if (!book_has_flags(book, FAST_BOOK_JOIN)) goto done; if (dst && dst->secid != book->secid) goto done; } else { field = fast_get_field(msg, "Symbol"); if (!field || field_state_empty(field)) goto fail; book = fast_book_by_symbol(set, field->string_value); if (!book || book_has_flags(book, FAST_BOOK_ACTIVE)) goto done; if (!book_has_flags(book, FAST_BOOK_JOIN)) goto done; if (dst && strncmp(book->symbol, dst->symbol, strlen(dst->symbol))) goto done; } field = fast_get_field(msg, "MDEntries"); if (!field) { field = fast_get_field(msg, "GroupMDEntries"); } if (!field || field_state_empty(field)) goto fail; seq = field->ptr_value; if (field_state_empty(&seq->length)) goto fail; if (!seq->length.uint_value) goto done; md = seq->elements; field = fast_get_field(md, "TradingSessionID"); if (field) { if (field_state_empty(field)) goto fail; if (strncmp(book->session, field->string_value, strlen(book->session))) goto done; } field = fast_get_field(msg, "RptSeq"); if (!field || field_state_empty(field)) goto fail; book->snpseq = field->uint_value; book_clear_flags(book, FAST_BOOK_EMPTY); book_add_mask(set, book); for (i = 1; i <= seq->length.uint_value; i++) { md = seq->elements + i; if (md_snapshot(book, md)) goto fail; } if (!book_has_flags(book, FAST_BOOK_EMPTY)) book_add_flags(book, FAST_BOOK_ACTIVE); done: return 0; fail: return -1; }