// handler if we get a SIGTERM/SIGINT. make sure to clean up properly from // these and treat as normal termination. static void termination_handler(int signal) { // can't normally terminate in the middle of handling a transaction. if (handling_transaction) { logout << "ERROR: Signal received while handling transaction, aborting..." << endl << flush; abort(); } // ignore multiple signals. static bool terminating = false; if (terminating) return; terminating = true; logout << "Termination signal received, finishing..." << endl << flush; close(server_socket); ClearBlockCaches(); ClearMemoryCaches(); AnalysisFinish(0); }
int main(int argc, const char **argv) { plain_text.Enable(); raw_tags.Enable(); Vector<const char*> unspecified; bool parsed = Config::Parse(argc, argv, &unspecified); if (!parsed || unspecified.Size() != 2) { Config::PrintUsage(USAGE); return 1; } // we're only doing one access, we don't need the key cache Xdb::DisableKeyCache(); AnalysisPrepare(); const char *file = unspecified[0]; const char *key = unspecified[1]; Xdb *xdb = new Xdb(file, false, false, true); if (!xdb->Exists()) { delete xdb; return 0; } Buffer bkey((const uint8_t*) key, strlen(key) + 1); Buffer cdata; Buffer bdata; bool success = xdb->Find(&bkey, &cdata); if (success) { UncompressBufferInUse(&cdata, &bdata); size_t len = bdata.pos - bdata.base; if (plain_text.IsSpecified()) { for (size_t n = 0; n < len; n++) logout << (char) bdata.base[n]; logout << endl; } else if (raw_tags.IsSpecified()) { size_t consumed = 0; while (consumed != len) { Buffer parse_data(bdata.base + consumed, len - consumed); parse_data.pos += len - consumed; size_t read_len = PrintPartialBuffer(&parse_data); if (read_len == 0) break; consumed += read_len; } } else { Buffer read_buf(bdata.base, len); while (read_buf.pos != read_buf.base + len) { HashObject *value = ReadSingleValue(&read_buf); logout << value << endl; } } } delete xdb; ClearBlockCaches(); ClearMemoryCaches(); AnalysisFinish(0); }
void handle_event(int fd, short, void *v) { bool success; size_t index = (size_t) v; Assert(index < connections.Size()); ConnectData *cdata = connections[index]; Assert(cdata->live); if (cdata->write_buf.size != 0) { success = WritePacket(fd, &cdata->write_buf); if (success) { cdata->write_buf.base = NULL; cdata->write_buf.pos = NULL; cdata->write_buf.size = 0; } } else { size_t length = cdata->read_buf.pos - cdata->read_buf.base; success = ReadPacket(fd, &cdata->read_buf); if (success) { size_t data_length = cdata->read_buf.pos - cdata->read_buf.base - UINT32_LENGTH; Buffer transaction_buf(cdata->read_buf.base + UINT32_LENGTH, data_length); Transaction *t = new Transaction(); if (!t->Read(&transaction_buf)) { logout << "ERROR: Corrupt packet data" << endl; delete t; return; } handling_transaction = true; t->Execute(); cdata->read_buf.pos = cdata->read_buf.base; cdata->read_buf.Ensure(UINT32_LENGTH); cdata->read_buf.pos += UINT32_LENGTH; t->WriteResult(&cdata->read_buf); cdata->write_buf.base = cdata->read_buf.base; cdata->write_buf.pos = cdata->write_buf.base; cdata->write_buf.size = cdata->read_buf.pos - cdata->read_buf.base; cdata->read_buf.pos = cdata->read_buf.base; success = WritePacket(fd, &cdata->write_buf); if (success) { cdata->write_buf.base = NULL; cdata->write_buf.pos = NULL; cdata->write_buf.size = 0; } // watch for initial and final transactions. if (t->IsInitial()) { Assert(!spawn_count.IsSpecified()); received_initial++; } if (t->IsFinal()) { Assert(received_final < received_initial); received_final++; if (received_final == received_initial) { // this was the last client, so cleanup and exit. logout << "Final transaction received, finishing..." << endl << flush; close(server_socket); ClearBlockCaches(); ClearMemoryCaches(); AnalysisFinish(0); } } delete t; handling_transaction = false; } else if ((ssize_t) length == cdata->read_buf.pos - cdata->read_buf.base) { // connection is closed. there is nothing to read so remove the event. event_del(&cdata->ev); close(cdata->fd); cdata->live = false; cdata->read_buf.Reset(0); cdata->write_buf.Reset(0); } } }