示例#1
0
static void
test_various_read_write_1 (const char *name,
                           unsigned   n_entries,
                           TestEntry *entries,
                           uint64_t   n_write)
{
  DskError *error = NULL;
  DskTableFileInterface *iface = &dsk_table_file_interface_trivial;
  uint64_t big_i;               /* index from 0..n_write-1 */
  uint32_t small_i;             /* index from 0..n_entries-1 */
  DskTableFileWriter *writer;
  DskTableReader *reader;

  if (cmdline_verbose)
    fprintf (stderr, "running dataset %s [%llu]\n", name, (unsigned long long) n_write);
  else
    fprintf (stderr, ".");

  writer = iface->new_writer (iface, location, "base", &error);
  if (writer == NULL)
    dsk_die ("%s", error->message);
  for (big_i = small_i = 0; big_i < n_write; big_i++)
    {
      TestEntry *e = entries + small_i++;
      if (small_i == n_entries)
        small_i = 0;
      if (!writer->write (writer,
                          strlen (e->key), (uint8_t*) e->key,
                          strlen (e->value), (uint8_t*) e->value,
                          &error))
        dsk_die ("error writing: %s", error->message);
    }
  if (!writer->close (writer, &error))
    dsk_die ("error closing writer: %s", error->message);
  writer->destroy (writer);

  reader = iface->new_reader (iface, location, "base", &error);
  if (reader == NULL)
    dsk_die ("error creating reader: %s", error->message);
  small_i = 0;
  for (big_i = 0; big_i < n_write; big_i++)
    {
      TestEntry *e = entries + small_i++;
      if (small_i == n_entries)
        small_i = 0;

      dsk_assert (!reader->at_eof);
      dsk_assert (reader->key_length == strlen (e->key));
      dsk_assert (reader->value_length == strlen (e->value));
      dsk_assert (memcmp (reader->key_data, e->key, reader->key_length) == 0);
      dsk_assert (memcmp (reader->value_data, e->value, reader->value_length) == 0);

      if (!reader->advance (reader, &error))
        dsk_die ("error reading file: %s", error->message);
      if (big_i + 1 == n_write)
        break;
    }
  dsk_assert (reader->at_eof);
  reader->destroy (reader);
}
示例#2
0
int main(int argc, char **argv)
{
  unsigned port = 0;
  DskHttpServer *server;
  unsigned i;
  DskError *error = NULL;

  dsk_cmdline_init ("snipez server", "Run a snipez server", NULL, 0);
  dsk_cmdline_add_uint ("port", "Port Number",
                        "PORT", DSK_CMDLINE_MANDATORY, &port);
  dsk_cmdline_add_uint ("update-period", "Update Period",
                        "MILLIS", 0, &update_period_msecs);
  dsk_cmdline_add_func ("make-maze", "Make a Maze",
                        "WIDTHxHEIGHT", DSK_CMDLINE_OPTIONAL,
                        handle_make_maze, NULL);
  dsk_cmdline_add_shortcut ('p', "port");
  dsk_cmdline_process_args (&argc, &argv);

  server = dsk_http_server_new ();
  for (i = 0; i < DSK_N_ELEMENTS (handlers); i++)
    {
      dsk_http_server_match_save (server);
      dsk_http_server_add_match (server, DSK_HTTP_SERVER_MATCH_PATH,
                                 handlers[i].pattern);
      dsk_http_server_register_cgi_handler (server,
                                            (DskHttpServerCgiFunc) handlers[i].handler,
                                            NULL, NULL);
      dsk_http_server_match_restore (server);
    }
  if (!dsk_http_server_bind_tcp (server, NULL, port, &error))
    dsk_die ("error binding to port %u: %s", port, error->message);

  return dsk_main_run ();
}
示例#3
0
int main(int argc, char **argv)
{
  unsigned i;
  char test_dir_buf[256];
  DskError *error = NULL;

  dsk_cmdline_init ("test table internals (the 'file' abstraction)",
                    "Test Table Internals",
                    NULL, 0);
  dsk_cmdline_add_boolean ("verbose", "extra logging", NULL, 0,
                           &cmdline_verbose);
  dsk_cmdline_add_boolean ("slow", "run tests that are fairly slow", NULL, 0,
                           &cmdline_slow);
  dsk_cmdline_add_boolean ("keep-testdir", "do not delete working directory", NULL, 0,
                           &cmdline_keep_testdir);
  dsk_cmdline_process_args (&argc, &argv);

  snprintf (test_dir_buf, sizeof (test_dir_buf),
            "test-table-file-%u-%u", (unsigned)time(NULL), (unsigned)getpid());
  location = dsk_dir_new (NULL, test_dir_buf, DSK_DIR_NEW_MAYBE_CREATE, &error);
  if (location == NULL)
    dsk_die ("error making directory: %s", error->message);

  for (i = 0; i < DSK_N_ELEMENTS (tests); i++)
    {
      fprintf (stderr, "Test: %s... ", tests[i].name);
      tests[i].test ();
      fprintf (stderr, " done.\n");
    }

  if (cmdline_keep_testdir)
    {
      fprintf (stderr,
               "test-table-file: keep-testdir: preserving test directory %s\n",
               dsk_dir_get_str (location));
    }
  else
    {
      DskError *error = NULL;
      if (!dsk_remove_dir_recursive (dsk_dir_get_str (location), &error))
        dsk_die ("error removing directory %s: %s",
                 dsk_dir_get_str (location), error->message);
    }
  dsk_cleanup ();
  return 0;
}
示例#4
0
static DskHttpRequest *
parse_request_from_string (const char *str)
{
  DskError *error = NULL;
  DskHttpRequest *rv = try_parse_request_from_string (str, &error);
  if (rv == NULL)
    dsk_die ("error parsing request from string: %s", error->message);
  return rv;
}
示例#5
0
static void
maybe_redirect_stdouterr (void)
{
  if (dsk_daemon_log_template == NULL)
    return;

  time_t t = time (NULL);
  char buf[2048];
  struct tm tm;
  t += dsk_daemon_tzoffset;
  gmtime_r (&t, &tm);
  strftime (buf, sizeof (buf), dsk_daemon_log_template, &tm);

  int fd;
  dsk_boolean made_dir = DSK_FALSE;
retry_open:
  fd = open (buf, O_WRONLY|O_APPEND|O_CREAT, 0666);
  if (fd < 0)
    {
      if (errno == EINTR)
        goto retry_open;
      dsk_fd_creation_failed (errno);
      if (errno == ENOENT && !made_dir)
        {
          char *slash = strrchr (buf, '/');
          if (slash != NULL)
            {
              char *dir = dsk_strdup_slice (buf, slash);
              DskError *error = NULL;
              if (!dsk_mkdir_recursive (dir, 0777, &error))
                dsk_die ("error making directory %s: %s", dir, error->message);
              dsk_free (dir);
            }
          made_dir = DSK_TRUE;
          goto retry_open;
        }
      dsk_die ("error creating %s: %s", buf, strerror (errno));
    }
  fflush (stdout);
  fflush (stderr);
  dup2 (fd, STDOUT_FILENO);
  dup2 (fd, STDERR_FILENO);
  close (fd);
}
示例#6
0
文件: dsk-grep.c 项目: davebenson/dsk
int main(int argc, char **argv)
{
  DskPattern *pattern;
  DskError *error = NULL;
  dsk_cmdline_init ("grep-like tool",
                    "Implement 'grep' using DskPattern",
		    "PATTERN [FILES...]",
		    DSK_CMDLINE_PERMIT_ARGUMENTS);

  dsk_cmdline_process_args (&argc, &argv);

  if (argc < 2)
    dsk_die ("missing pattern");
  DskPatternEntry entry = { argv[1], "nonnull" };
  pattern = dsk_pattern_compile (1, &entry, &error);
  if (pattern == NULL)
    dsk_die ("error compiling pattern: %s", error->message);

  unsigned buffer_size = isatty (STDOUT_FILENO) ? 0 : 8192;
  
  if (argc == 2)
    handle_fd (pattern, NULL, buffer_size, 0);
  else
    {
      int i;
      for (i = 2; i < argc; i++)
        {
          int fd = open (argv[i], O_RDONLY);
          if (fd < 0)
            dsk_die ("error opening %s: %s", argv[i], strerror (errno));
          handle_fd (pattern, argc == 3 ? NULL : argv[i], buffer_size, fd);
          close (fd);
        }
    }
  return 0;
}
示例#7
0
static void
begin_connecting (DskClientStream *stream)
{
  if (stream->is_local_socket)
    {
      struct sockaddr_un addr;
      unsigned length = strlen (stream->name);
      if (length > sizeof (addr.sun_path))
        {
          /* name too long */
          /* TODO: catch this in constructor */
          dsk_octet_stream_set_last_error (&stream->base_instance,
                                           "name too long for local socket");

          return;
        }
      addr.sun_family = AF_LOCAL;
      memcpy (addr.sun_path, stream->name,
              length == sizeof (addr.sun_path) ? length : length + 1);
      begin_connecting_sockaddr (stream, sizeof (addr), (struct sockaddr *) &addr);
    }
  else if (stream->is_numeric_name)
    {
      struct sockaddr_storage addr;
      unsigned addr_len;
      DskIpAddress address;

      /* parse name into addr/addr_len */
      if (!dsk_ip_address_parse_numeric (stream->name, &address))
        dsk_die ("dsk_ip_address_parse_numeric failed on %s", stream->name);
      dsk_ip_address_to_sockaddr (&address, stream->port, &addr, &addr_len);
      begin_connecting_sockaddr (stream, addr_len, (struct sockaddr *) &addr);
    }
  else
    {
      /* begin dns lookup */
      stream->is_resolving_name = 1;
      dsk_object_ref (stream);
      dsk_dns_lookup (stream->name,
                      DSK_FALSE,                /* is_ipv6? should be be needed */
                      handle_dns_done, stream);
    }
}
示例#8
0
static void
test_simple_write_read (void)
{
  DskError *error = NULL;
  DskTableFileInterface *iface = &dsk_table_file_interface_trivial;

  DskTableFileWriter *writer = iface->new_writer (iface, location, "base", &error);
  DskTableReader *reader;
  if (writer == NULL)
    dsk_die ("%s", error->message);
  if (!writer->write (writer, 1, (uint8_t*) "a", 1, (uint8_t*) "A", &error)
   || !writer->write (writer, 1, (uint8_t*) "b", 1, (uint8_t*) "B", &error)
   || !writer->write (writer, 1, (uint8_t*) "c", 1, (uint8_t*) "C", &error))
    dsk_die ("error writing: %s", error->message);
  if (!writer->close (writer, &error))
    dsk_die ("error closing writer: %s", error->message);
  writer->destroy (writer);

  reader = iface->new_reader (iface, location, "base", &error);
  if (reader == NULL)
    dsk_die ("error creating reader: %s", error->message);
  dsk_assert (!reader->at_eof);
  dsk_assert (reader->key_length == 1);
  dsk_assert (reader->key_data[0] == 'a');
  dsk_assert (reader->value_length == 1);
  dsk_assert (reader->value_data[0] == 'A');
  if (!reader->advance (reader, &error))
    dsk_die ("error advancing reader: %s", error->message);
  dsk_assert (!reader->at_eof);
  dsk_assert (reader->key_length == 1);
  dsk_assert (reader->key_data[0] == 'b');
  dsk_assert (reader->value_length == 1);
  dsk_assert (reader->value_data[0] == 'B');
  if (!reader->advance (reader, &error))
    dsk_die ("error advancing reader: %s", error->message);
  dsk_assert (!reader->at_eof);
  dsk_assert (reader->key_length == 1);
  dsk_assert (reader->key_data[0] == 'c');
  dsk_assert (reader->value_length == 1);
  dsk_assert (reader->value_data[0] == 'C');
  if (!reader->advance (reader, &error))
    dsk_die ("error advancing reader: %s", error->message);
  dsk_assert (reader->at_eof);
  reader->destroy (reader);
}
示例#9
0
void dsk_daemon_maybe_fork (void)
{
  int fork_pipe_fds[2] = {-1,-1};
  if (dsk_daemon_do_fork)
    {
      int pid;
    retry_pipe:
      if (pipe (fork_pipe_fds) < 0)
        {
	  if (errno == EINTR)
	    goto retry_pipe;
          dsk_fd_creation_failed (errno);
	  dsk_die ("error creating pipe: %s", strerror (errno));
	}
    retry_daemon_fork:
      pid = fork ();
      if (pid < 0)
        {
	  if (errno == EINTR)
	    goto retry_daemon_fork;
	  dsk_die ("error forking daemon: %s", strerror (errno));
	}
      else if (pid > 0)
        {
	  /* wait for EOF on pipe */
	  close (fork_pipe_fds[1]);
	  char buf[1];
	  for (;;)
	    {
	      int nread = read (fork_pipe_fds[0], buf, 1);
	      if (nread < 0)
	        {
		  if (errno == EINTR)
		    continue;
		  dsk_die ("error reading from semaphore pipe: %s", strerror (errno));
		}
              else if (nread > 0)
		dsk_die ("somehow got data on semaphore pipe: %s:%u", __FILE__, __LINE__);
	      else
	        break;
	    }
	  _exit (0);
        }
      else
        {
	  /* child process: continue as the non-forking case. */
	  close (fork_pipe_fds[0]);
          setsid ();
	}
    }
  int pid_file_fd = -1;
  if (dsk_daemon_pid_filename)
    {
      dsk_boolean must_truncate = DSK_FALSE;
      dsk_boolean made_dir = DSK_FALSE;

retry_outer_pid_file_open:
      if ((pid_file_fd=open (dsk_daemon_pid_filename, O_CREAT|O_EXCL|O_WRONLY, 0666)) < 0)
        {
          if (errno == EINTR)
            goto retry_outer_pid_file_open;
          else if (errno == EEXIST)
            {
              /* open / lock-nonblocking / rewrite we get lock */
retry_inner_pid_file_open:
              if ((pid_file_fd=open (dsk_daemon_pid_filename, O_WRONLY, 0666)) < 0)
                {
                  if (errno == EINTR)
                    goto retry_inner_pid_file_open;
                  dsk_die ("daemonize: error opening lock file %s: %s", dsk_daemon_pid_filename,
                           strerror (errno));
                }
              must_truncate = DSK_TRUE;
            }
          else if (errno == ENOENT && !made_dir)
            {
              /* make directories, retry */
              char *slash = strrchr (dsk_daemon_pid_filename, '/');
              if (slash == NULL)
                dsk_die ("daemonize: error creating %s: no such file or dir (cwd does not exist?)", dsk_daemon_pid_filename);
              char *dir = dsk_strdup_slice (dsk_daemon_pid_filename, slash);
              DskError *error = NULL;
              if (!dsk_mkdir_recursive (dir, 0777, &error))
                dsk_die ("error making directory %s: %s", dir, error->message);
              dsk_free (dir);
              made_dir = DSK_TRUE;
              goto retry_outer_pid_file_open;
            }
          else
            {
              dsk_fd_creation_failed (errno);
              dsk_die ("daemonize: error creating PID file %s: %s",
                       dsk_daemon_pid_filename, strerror (errno));
            }
        }
retry_flock:
      if (flock (pid_file_fd, LOCK_EX|LOCK_NB) < 0)
        {
          if (errno == EINTR)
            goto retry_flock;
          if (errno == EWOULDBLOCK)
            {
              /* TODO: print PID */
              dsk_die ("daemonize: process already running");
            }
          dsk_die ("daemonize: error locking: %s", strerror (errno));
        }
      if (must_truncate)
        {
          ftruncate (pid_file_fd, 0);
        }
      char buf[32];
      snprintf (buf, sizeof (buf), "%u\n", (unsigned)getpid ());
      unsigned len = strlen (buf);
      unsigned written = 0;
      while (written < len)
        {
          int write_rv = write (pid_file_fd, buf + written, len - written);
          if (write_rv < 0)
            {
              if (errno == EINTR)
                continue;
              dsk_die ("error writing pid file %s", dsk_daemon_pid_filename);
            }
          written += write_rv;
        }
    }
  if (fork_pipe_fds[1] != -1)
    {
      close (fork_pipe_fds[1]);
    }

  if (dsk_daemon_watchdog)
    {
      int alert_pid = 0;
      unsigned last_alert_time = 0;
      for (;;)
        {
	  /* NOTE: must never die, i guess */
          int pid;
          int status;

retry_watchdog_fork:
	  pid = fork ();
	  if (pid < 0)
	    {
	      if (errno == EINTR)
	        goto retry_watchdog_fork;
              dsk_die ("error forking watchdogged process: %s", strerror (errno));
	    }
	  else if (pid == 0)
	    {
              if (pid_file_fd >= 0)
                close (pid_file_fd);
              maybe_redirect_stdouterr ();
              add_maybe_redirect_timer ();
	      return;
	    }
	  maybe_redirect_stdouterr ();
          char time_str[TIME_STR_LENGTH];
	  make_time_str (time_str);
	  fprintf (stderr, "%s: watchdog: forked process %u\n",
	           time_str, (unsigned) pid);
retry_waitpid:
          if (waitpid (pid, &status, 0) < 0)
	    {
	      if (errno == EINTR)
		goto retry_waitpid;
	      dsk_die ("error running waitpid %u: %s", pid, strerror (errno));
	    }
	  maybe_redirect_stdouterr ();
	  make_time_str (time_str);
	  if (WIFEXITED (status))
	    fprintf (stderr, "%s: watchdog: process %u exited with status %u\n",
		     time_str, pid, WEXITSTATUS (status));
	  else if (WIFSIGNALED (status))
	    fprintf (stderr, "%s: watchdog: process %u killed by signal %u%s\n",
		     time_str, pid, WTERMSIG (status),
		     WCOREDUMP (status) ? " [core dumped]" : "");
          else
	    fprintf (stderr, "%s: watchdog: process %u died in some creative way\n",
		     time_str, pid);

          /* configurable? */
          sleep (1);

	  /* send alert */
	  if (dsk_daemon_alert_script)
	    {
	      int time_delta = time (NULL) - last_alert_time;
              unsigned clamped_delta = time_delta < 0 ? 0 : time_delta;
              if (alert_pid > 0)
                {
                  int rv = waitpid (alert_pid, &status, WNOHANG);
                  if (rv < 0)
                    {
                      if (errno == EINTR)
                        goto retry_waitpid;
                      else
                        dsk_die ("error waiting for alert process");
                    }
                  else if (rv == 0)
                    {
                      /* process has not terminated */
                    }
                  else
                    {
                      /* process terminated (ignore status?) */
                      alert_pid = 0;
                    }
                }
	      if (alert_pid == 0 && clamped_delta > dsk_daemon_alert_interval)
	        {
                  retry_alert_fork:
                  alert_pid = fork ();
                  if (alert_pid < 0)
                    {
                      if (errno == EINTR)
                        goto retry_alert_fork;
                      dsk_warning ("error forking alert process: %s", strerror (errno));
                      alert_pid = 0;
                    }
                  else if (alert_pid == 0)
                    {
                      execl ("/bin/sh", "/bin/sh", "-c", dsk_daemon_alert_script, NULL);
                      _exit (127);
                    }
                  else
                    dsk_daemon_n_alerts_suppressed = 0;
		}
              else
	        ++dsk_daemon_n_alerts_suppressed;
	    }
	}
    }
}
示例#10
0
static void
test_various_write_seek_1 (const char *name,
                           unsigned    n_entries,
                           TestEntry  *entries,
                           unsigned    n_negative,
                           TestEntry  *neg_entries)
{
  DskError *error = NULL;
  unsigned i;
  DskTableFileInterface *iface = &dsk_table_file_interface_trivial;
  DskTableFileWriter *writer;
  DskTableFileSeeker *seeker;

  if (cmdline_verbose)
    fprintf (stderr, "running dataset %s [%u]\n", name, n_entries);
  else
    fprintf (stderr, ".");

  writer = iface->new_writer (iface, location, "base", &error);
  if (writer == NULL)
    dsk_die ("%s", error->message);
  for (i = 0; i < n_entries; i++)
    {
      TestEntry *e = entries + i;
      if (!writer->write (writer,
                          strlen (e->key), (uint8_t*) e->key,
                          strlen (e->value), (uint8_t*) e->value,
                          &error))
        dsk_die ("error writing: %s", error->message);
    }
  if (!writer->close (writer, &error))
    dsk_die ("error closing writer: %s", error->message);
  writer->destroy (writer);

  /* --- now test seeker --- */

  /* pick the step size. */
  {
  static unsigned prime_table[] = { 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 };
  unsigned *p_ptr = prime_table + DSK_N_ELEMENTS (prime_table) - 1;
  unsigned max_test, n_test, test_i, step;
  while (n_entries % *p_ptr == 0)
    p_ptr--;
  step = *p_ptr % n_entries;

  /* create seeker */
  seeker = iface->new_seeker (iface, location, "base", &error);
  if (seeker == NULL)
    dsk_die ("error creating seeker from newly finished writer: %s",
             error->message);

  max_test = cmdline_slow ? 100000 : 1000;
  n_test = DSK_MIN (n_entries, max_test);
  test_i = step;
  for (i = 0; i < n_test; i++)
    {
      unsigned key_len, value_len;
      const uint8_t *key_data, *value_data;
      /* do the seek */
      if (!seeker->find (seeker,
                         str_test_func,
                         (void*) entries[test_i].key,
                         DSK_TABLE_FILE_FIND_ANY,
                         &key_len, &key_data,
                         &value_len, &value_data,
                         &error))
        {
          if (error)
            dsk_die ("error doing find that should have succeeded: %s",
                     error->message);
          else
            dsk_die ("not found doing find that should have succeeded");
        }
#if 0
      dsk_warning ("test=%s, got result %.*s", entries[test_i].key,
                   (int) key_len, key_data);
#endif
      dsk_assert (key_len == strlen (entries[test_i].key));
      dsk_assert (value_len == strlen (entries[test_i].value));
      dsk_assert (memcmp (key_data, entries[test_i].key, key_len) == 0);
      dsk_assert (memcmp (value_data, entries[test_i].value, value_len) == 0);

      /* advance test_i */
      test_i += step;
      if (test_i >= n_entries)
        test_i -= n_entries;
    }

  /* do negative tests */
  for (i = 0; i < n_negative; i++)
    {
      unsigned key_len, value_len;
      const uint8_t *key_data, *value_data;
      /* do the seek */
      if (!seeker->find (seeker,
                         str_test_func,
                         (void*) neg_entries[i].key,
                         DSK_TABLE_FILE_FIND_ANY,
                         &key_len, &key_data,
                         &value_len, &value_data,
                         &error))
        {
          if (error)
            dsk_die ("error doing find that should have returned nothing: %s",
                     error->message);
        }
      else if (key_len == strlen (neg_entries[i].key)
               && memcmp (key_data, neg_entries[i].key, key_len) == 0)
        {
          dsk_die ("found result when none expected");
        }
    }


  seeker->destroy (seeker);
  }
}