/* * Gets a reply from the MongoDB server and * creates a cursor for it */ int mongo_link_hear(SV *cursor_sv) { int sock; int num_returned = 0; mongo_cursor *cursor = (mongo_cursor*)perl_mongo_get_ptr_from_instance(cursor_sv); SV *link_sv = perl_mongo_call_reader(cursor_sv, "_connection"); mongo_link *link = (mongo_link*)perl_mongo_get_ptr_from_instance(link_sv); if (!check_connection(link)) { SvREFCNT_dec(link_sv); croak("can't get db response, not connected"); return 0; } sock = perl_mongo_link_master(link_sv); // if this fails, we might be disconnected... but we're probably // just out of results if (recv(sock, (char*)&cursor->header.length, INT_32, 0) == -1) { SvREFCNT_dec(link_sv); return 0; } cursor->header.length = MONGO_32(cursor->header.length); // make sure we're not getting crazy data if (cursor->header.length > MAX_RESPONSE_LEN || cursor->header.length < REPLY_HEADER_SIZE) { set_disconnected(link); if (!check_connection(link)) { SvREFCNT_dec(link_sv); croak("bad response length: %d, max: %d, did the db assert?\n", cursor->header.length, MAX_RESPONSE_LEN); return 0; } } if (recv(sock, (char*)&cursor->header.request_id, INT_32, 0) == -1 || recv(sock, (char*)&cursor->header.response_to, INT_32, 0) == -1 || recv(sock, (char*)&cursor->header.op, INT_32, 0) == -1 || recv(sock, (char*)&cursor->flag, INT_32, 0) == -1 || recv(sock, (char*)&cursor->cursor_id, INT_64, 0) == -1 || recv(sock, (char*)&cursor->start, INT_32, 0) == -1 || recv(sock, (char*)&num_returned, INT_32, 0) == -1) { SvREFCNT_dec(link_sv); return 0; } cursor->header.request_id = MONGO_32(cursor->header.request_id); cursor->header.response_to = MONGO_32(cursor->header.response_to); cursor->header.op = MONGO_32(cursor->header.op); cursor->flag = MONGO_32(cursor->flag); cursor->cursor_id = MONGO_64(cursor->cursor_id); cursor->start = MONGO_32(cursor->start); num_returned = MONGO_32(num_returned); // create buf cursor->header.length -= INT_32*9; // point buf.start at buf's first char if (!cursor->buf.start) { New(0, cursor->buf.start, cursor->header.length, char); cursor->buf.end = cursor->buf.start + cursor->header.length; }
void mcon_serialize_int64(struct mcon_str *str, int64_t num) { int64_t i = MONGO_64(num); mcon_str_addl(str, (char*) &i, 8, 0); }
/* * Gets a reply from the MongoDB server and * creates a cursor for it */ int mongo_link_hear(SV *cursor_sv) { int sock; int num_returned = 0, timeout = -1; mongo_cursor *cursor; mongo_link *link; SV *link_sv, *request_id_sv, *timeout_sv; cursor = (mongo_cursor*)perl_mongo_get_ptr_from_instance(cursor_sv); link_sv = perl_mongo_call_reader(cursor_sv, "_connection"); link = (mongo_link*)perl_mongo_get_ptr_from_instance(link_sv); timeout_sv = perl_mongo_call_reader(link_sv, "query_timeout"); if ((sock = perl_mongo_master(link_sv)) == -1) { set_disconnected(link_sv); SvREFCNT_dec(link_sv); croak("can't get db response, not connected"); } timeout = SvIV(timeout_sv); SvREFCNT_dec(timeout_sv); // set a timeout if (timeout >= 0) { struct timeval t; fd_set readfds; t.tv_sec = timeout / 1000 ; t.tv_usec = (timeout % 1000) * 1000; FD_ZERO(&readfds); FD_SET(sock, &readfds); select(sock+1, &readfds, NULL, NULL, &t); if (!FD_ISSET(sock, &readfds)) { SvREFCNT_dec(link_sv); croak("recv timed out (%d ms)", timeout); return 0; } } if (get_header(sock, cursor_sv, link_sv) == 0) { SvREFCNT_dec(link_sv); return 0; } request_id_sv = perl_mongo_call_reader(cursor_sv, "_request_id"); while (SvIV(request_id_sv) != cursor->header.response_to) { char temp[4096]; int len = cursor->header.length - 36; if (SvIV(request_id_sv) < cursor->header.response_to) { SvREFCNT_dec(link_sv); SvREFCNT_dec(request_id_sv); croak("missed the response we wanted, please try again"); return 0; } if (recv(sock, (char*)temp, 20, 0) == -1) { SvREFCNT_dec(link_sv); SvREFCNT_dec(request_id_sv); croak("couldn't get header response to throw out"); return 0; } do { int temp_len = len > 4096 ? 4096 : len; len -= temp_len; if (mongo_link_reader(sock, (void*)temp, temp_len) == -1) { SvREFCNT_dec(link_sv); SvREFCNT_dec(request_id_sv); croak("couldn't get response to throw out"); return 0; } } while (len > 0); if (get_header(sock, cursor_sv, link_sv) == 0) { SvREFCNT_dec(link_sv); SvREFCNT_dec(request_id_sv); return 0; } } SvREFCNT_dec(request_id_sv); if (recv(sock, (char*)&cursor->flag, INT_32, 0) == -1 || recv(sock, (char*)&cursor->cursor_id, INT_64, 0) == -1 || recv(sock, (char*)&cursor->start, INT_32, 0) == -1 || recv(sock, (char*)&num_returned, INT_32, 0) == -1) { SvREFCNT_dec(link_sv); croak("%s", strerror(errno)); return 0; } SvREFCNT_dec(link_sv); cursor->flag = MONGO_32(cursor->flag); // if zero-th bit is set, cursor is invalid if (cursor->flag & 1) { cursor->num = 0; croak("cursor not found"); } cursor->cursor_id = MONGO_64(cursor->cursor_id); cursor->start = MONGO_32(cursor->start); num_returned = MONGO_32(num_returned); // create buf cursor->header.length -= INT_32*9; // point buf.start at buf's first char if (!cursor->buf.start) { New(0, cursor->buf.start, cursor->header.length, char); cursor->buf.end = cursor->buf.start + cursor->header.length; }