Пример #1
0
static void string_stream_tests(void)
{
  ph_string_t *str;
  ph_stream_t *stm;
  char buf[5];
  uint64_t r;

  str = ph_string_make_empty(mt_misc, 16);
  stm = ph_stm_string_open(str);
  ok(stm, "made a stream");

  ph_stm_printf(stm, "hello world");
  ok(ph_string_equal_cstr(str, "hello world"), "see printf");

  ok(ph_stm_seek(stm, 0, SEEK_SET, NULL), "rewound");
  ok(ph_stm_read(stm, buf, sizeof(buf), &r), "read data");
  is(r, sizeof(buf));
  is(memcmp(buf, "hello", 5), 0);

  ph_stm_printf(stm, " kitty and append!");
  ok(ph_string_equal_cstr(str, "hello kitty and append!"), "see printf");

  ok(ph_stm_seek(stm, 6, SEEK_SET, NULL), "rewound");
  ok(ph_stm_read(stm, buf, sizeof(buf), &r), "read data");
  is(r, sizeof(buf));
  is(memcmp(buf, "kitty", 5), 0);

  ok(ph_stm_seek(stm, -5, SEEK_END, NULL), "rewound");
  ok(ph_stm_read(stm, buf, sizeof(buf), &r), "read data");
  is(r, sizeof(buf));
  is(memcmp(buf, "pend!", 5), 0);

  ph_stm_close(stm);
  ph_string_delref(str);
}
Пример #2
0
int main(int argc, char **argv)
{
  ph_stream_t *stm;
  char namebuf[128];
  int fd;
  char buf[BUFSIZ];
  uint64_t amount;
  int len;

  ph_unused_parameter(argc);
  ph_unused_parameter(argv);

  ph_library_init();
  plan_tests(18);

  strcpy(namebuf, "/tmp/phenomXXXXXX");
  fd = ph_mkostemp(namebuf, 0);
  diag("opened %s -> %d", namebuf, fd);
  unlink(namebuf);

  stm = ph_stm_fd_open(fd, 0, PH_STM_BUFSIZE);
  ph_stm_write(stm, "lemon\n", 6, &amount);
  is(amount, 6);

  // Shouldn't see it yet
  is(0, pread(fd, buf, sizeof(buf), 0));

  // Should see it now
  ph_stm_flush(stm);
  is(6, pread(fd, buf, sizeof(buf), 0));

  ok(!memcmp("lemon\n", buf, 6), "right content");
  ok(ph_stm_seek(stm, 0, SEEK_SET, NULL), "seeked");
  memset(buf, 0, sizeof(buf));

  ok(ph_stm_read(stm, buf, 3, &amount), "read ok");
  ok(amount == 3, "amount is %" PRIu64, amount);
  ok(!memcmp("lem", buf, 3), "got prefix");

  ok(ph_stm_read(stm, buf, 3, &amount), "read ok");
  ok(amount == 3, "amount is %" PRIu64, amount);
  ok(!memcmp("on\n", buf, 3), "got remainder");

  ok(ph_stm_seek(stm, 0, SEEK_SET, NULL), "seeked");
  len = ph_stm_printf(stm, "testing %d %s!", 1, "two");
  ok(14 == len, "printed len %d", len);
  ok(ph_stm_seek(stm, 0, SEEK_SET, NULL), "seeked");
  memset(buf, 0, sizeof(buf));
  ok(ph_stm_read(stm, buf, 14, &amount), "read ok");
  ok(amount == 14, "len was %" PRIu64, amount);
  ok(!memcmp("testing 1 two!", buf, 14), "got formatted");

  ok(ph_stm_close(stm), "closed");

  return exit_status();
}
Пример #3
0
// Query memory stats
static void cmd_memory(ph_sock_t *sock)
{
  ph_mem_stats_t stats[1];
  ph_memtype_t base = PH_MEMTYPE_FIRST;
  char name[29];

  ph_stm_printf(sock->stream,
      "%28s %9s %9s %9s %9s %9s\r\n",
      "WHAT", "BYTES", "OOM", "ALLOCS", "FREES", "REALLOC"
  );

  while (1) {
    int n, i;

    n = ph_mem_stat_range(base,
          base + (sizeof(stats) / sizeof(stats[0])), stats);

    for (i = 0; i < n; i++) {
      ph_snprintf(name, sizeof(name),
          "%s/%s", stats[i].def->facility, stats[i].def->name);

      ph_stm_printf(sock->stream,
          "%28s "
          "%9"PRIu64" "
          "%9"PRIu64" "
          "%9"PRIu64" "
          "%9"PRIu64" "
          "%9"PRIu64" "
          "\r\n",
          name,
          stats[i].bytes, stats[i].oom, stats[i].allocs,
          stats[i].frees, stats[i].reallocs);
    }

    if ((uint32_t)n < sizeof(stats) / sizeof(stats[0])) {
      break;
    }

    base += n;
  }
}
Пример #4
0
// Called each time the session wakes up.
// The `why` parameter indicates why we were woken up
static void echo_processor(ph_sock_t *sock, ph_iomask_t why, void *arg)
{
  struct echo_state *state = arg;
  ph_buf_t *buf;

  // If the socket encountered an error, or if the timeout was reached
  // (there's a default timeout, even if we didn't override it), then
  // we tear down the session
  if (why & (PH_IOMASK_ERR|PH_IOMASK_TIME)) {
    ph_log(PH_LOG_ERR, "disconnecting `P{sockaddr:%p}", (void*)&sock->peername);
    ph_sock_shutdown(sock, PH_SOCK_SHUT_RDWR);
    ph_mem_free(mt_state, state);
    ph_sock_free(sock);
    return;
  }

  // We loop because echo_processor is only triggered by newly arriving
  // data or events from the kernel.  If we have data buffered and only
  // partially consume it, we won't get woken up until the next data
  // arrives, if ever.
  while (1) {
    // Try to read a line of text.
    // This returns a slice over the underlying buffer (if the line was
    // smaller than a buffer) or a freshly made contiguous buffer (if the
    // line was larger than our buffer segment size).  Either way, we
    // own a reference to the returned buffer and should treat it as
    // a read-only slice.
    buf = ph_sock_read_line(sock);
    if (!buf) {
      // Not available yet, we'll try again later
      return;
    }

    // We got a line; update our state
    state->num_lines++;

    // Send our response.  The data is buffered and automatically sent
    // to the client as it becomes writable, so we don't need to handle
    // partial writes or EAGAIN here.

    // If this was a "real" server, we would still check the return value
    // from the writes and proceed to tear down the session if things failed.

    // Note that buf includes the trailing CRLF, so our response
    // will implicitly end with CRLF too.
    ph_stm_printf(sock->stream, "You said [%d]: ", state->num_lines);
    ph_stm_write(sock->stream, ph_buf_mem(buf), ph_buf_len(buf), NULL);

    // We're done with buf, so we must release it
    ph_buf_delref(buf);
  }
}
Пример #5
0
// Query all counters except for memory counters.
static void cmd_counters(ph_sock_t *sock)
{
#define NUM_SLOTS 64
#define NUM_COUNTERS 2048
  struct counter_name_val counter_data[NUM_COUNTERS];
  int64_t view_slots[NUM_SLOTS];
  const char *view_names[NUM_SLOTS];
  ph_counter_scope_iterator_t iter;
  uint32_t num_slots, i;
  uint32_t n_counters = 0;
  uint32_t longest_name = 0;
  char name[69];

  // Collect all counter data; it is returned in an undefined order.
  // For the sake of testing we want to order it, so we collect the data
  // and then sort it
  ph_counter_scope_iterator_init(&iter);
  ph_counter_scope_t *iter_scope;
  while ((iter_scope = ph_counter_scope_iterator_next(&iter)) != NULL) {
    uint32_t slen;

    if (strncmp(ph_counter_scope_get_name(iter_scope), "memory/", 7) == 0) {
      ph_counter_scope_delref(iter_scope);
      continue;
    }

    slen = strlen(ph_counter_scope_get_name(iter_scope));

    num_slots = ph_counter_scope_get_view(iter_scope, NUM_SLOTS,
        view_slots, view_names);

    for (i = 0; i < num_slots; i++) {
      uint32_t l = strlen(view_names[i]);

      longest_name = MAX(longest_name, l + slen + 1);
      counter_data[n_counters].scope_name =
        ph_counter_scope_get_name(iter_scope);
      counter_data[n_counters].name = view_names[i];
      counter_data[n_counters].val = view_slots[i];
      n_counters++;

      if (n_counters >= NUM_COUNTERS) {
        break;
      }
    }

    ph_counter_scope_delref(iter_scope);

    if (n_counters >= NUM_COUNTERS) {
      break;
    }
  }

  qsort(counter_data, n_counters, sizeof(struct counter_name_val),
      compare_counter_name_val);

  for (i = 0; i < n_counters; i++) {
    ph_snprintf(name, sizeof(name), "%s/%s",
        counter_data[i].scope_name,
        counter_data[i].name);
    ph_stm_printf(sock->stream, "%*s %16" PRIi64"\r\n",
        longest_name,
        name, counter_data[i].val);
  }

  if (n_counters >= NUM_COUNTERS) {
    ph_stm_printf(sock->stream,
        "WARNING: too many counters to sort, output truncated\r\n");
  }
}