// 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);
}
Esempio n. 2
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);
    }
  }
}