Exemple #1
0
Term *
func_op_names(TermList terms)
{
  Term *ops_t;

  ops_t  = (Term *)get_list_pos(terms, 1);
  if (! ops_t ) {
    report_fatal_external_error((char *)"Cannot retrieve OP instance term");
  }
  if (ops_t->type != LISP_LIST) {
    report_fatal_external_error((char *)"Term is not of type LISP_LIST");
  }

  TermList name_list = sl_make_slist();

  for (L_List p_l = ops_t->u.l_list; p_l; p_l = l_cdr(p_l)) {
    Term *t = l_car(p_l);
    if (t->type == TT_INTENTION) {
      Op_Instance *opi = (Op_Instance *)(t->u.in->top_op);
      Op_Structure *op_s = op_instance_op(opi);
      name_list = build_term_list(name_list, build_id(op_name(op_s)));
    } else if (t->type == TT_OP_INSTANCE) {
      Op_Instance *opi = (Op_Instance *)(t->u.opi);
      Op_Structure *op_s = op_instance_op(opi);
      if (! op_s) {
        name_list = build_term_list(name_list, build_id(declare_atom("NOT-AN-OP")));
      } else {
        name_list = build_term_list(name_list, build_id(op_name(op_s)));
      }
    } else {
      name_list = build_term_list(name_list, build_id(declare_atom("NOT-AN-OP-INSTANCE")));
    }
  }

  return build_term_l_list_from_c_list(name_list);
}
Exemple #2
0
Term *
func_op_name(TermList terms)
{
  Term *op_t;
  Op_Instance *opi;

  op_t  = (Term *)get_list_pos(terms, 1);
  if (! op_t ) {
    report_fatal_external_error((char *)"Cannot retrieve OP instance term");
  }
  if (op_t->type != TT_OP_INSTANCE) {
    report_fatal_external_error((char *)"Term is not of type OP_INSTANCE");
  }

  opi = (Op_Instance *)(op_t->u.opi);
  Op_Structure *op_s = op_instance_op(opi);
  if (! op_s) {
    report_fatal_external_error((char *)"Failed to get OP structure from OP instance");
  }

  return build_id(op_name(op_s));
}
Exemple #3
0
//  Main
int
main (int argc, char **argv)
{
        //  Do some initial sanity checking
        assert (TIME_BITLEN + MACHINE_BITLEN + SEQ_BITLEN == 64);

        //  Parse command-line arguments
        int opt;
        int has_port_opt = 0;
        int has_machine_opt = 0;
        int has_config_file_opt = 0;
        int has_daemonize_opt = 0;
        int machine_specified = 0;

        const char *config_file_path;
        int port = DEFAULT_PORT;
        uint64_t machine;
        
        while ((opt = getopt (argc, argv, "hp:m:f:d")) != -1) {
                switch (opt) {
                case 'h':
                        print_help ();
                        exit (EXIT_SUCCESS);
                case 'p':
                        has_port_opt = 1;
                        port = atoi (optarg);
                        break;
                case 'm':
                        has_machine_opt = 1;
                        machine = atoll (optarg);
                        machine_specified = 1;
                        break;
                case 'f':
                        has_config_file_opt = 1;
                        config_file_path = optarg;
                        break;
                case 'd':
                        has_daemonize_opt = 1;
                        break;
                }
        }

        //  Read the config file
        if (has_config_file_opt) {
                config_t cfg;

                config_init (&cfg);

                if (!config_read_file (&cfg, config_file_path)) {
                        config_destroy (&cfg);
                        fprintf (stderr, "Invalid config file\n");
                        exit (EXIT_FAILURE);
                }

                long unsigned int machine_from_file;
                if (config_lookup_int (&cfg, "machine", &machine_from_file) && !has_machine_opt) {
                        machine_specified = 1;
                        machine = (uint64_t) machine_from_file;
                }

                long unsigned int port_from_file;
                if (config_lookup_int (&cfg, "port", &port_from_file) && !has_port_opt)
                        port = (int) port_from_file;

                
        }

        //  Sanity check the machine number
        if (!machine_specified) {
                fprintf (stderr, "No machine number specified.\n");
                exit (EXIT_FAILURE);
        }
        else if (machine > MACHINE_MAX) {
                fprintf (stderr, "Machine number too large. Cannot be greater than %llu\n", MACHINE_MAX);
                exit (EXIT_FAILURE);
        }

        //  Daemonize
        static char *pid_file_path = "/var/run/znowflaked.pid";
        int pid_file;
        
        if (has_daemonize_opt) {
                pid_t pid, sid;

                pid = fork ();
                if (pid < 0) {
                        exit (EXIT_FAILURE);
                }
                if (pid > 0) {
                        exit (EXIT_SUCCESS);
                }

                umask (0);
                
                sid = setsid ();
                if (sid < 0) {
                        exit (EXIT_FAILURE);
                }
        
                if ((chdir ("/")) < 0) {
                        exit (EXIT_FAILURE);
                }

                //  Create and lock the pid file
                pid_file = open (pid_file_path, O_CREAT | O_RDWR, 0666);
                if (pid_file > 0) {
                        int rc = lockf (pid_file, F_TLOCK, 0);
                        if (rc) {
                                switch (errno) {
                                case EACCES:
                                case EAGAIN:
                                        fprintf (stderr, "PID file already locked\n");
                                        break;
                                case EBADF:
                                        fprintf (stderr, "Bad pid file\n");
                                        break;
                                default:
                                        fprintf (stderr, "Could not lock pid file\n");
                                }
                                exit (EXIT_FAILURE);
                        }

                        char *pid_string = NULL;
                        int pid_string_len = asprintf (&pid_string, "%ld", (long) getpid ());
                        write (pid_file, pid_string, pid_string_len);
                }
        
                close (STDIN_FILENO);
                close (STDOUT_FILENO);
                close (STDERR_FILENO);
        }

        //  Sleep for 1ms to prevent collisions
        struct timespec ms;
        ms.tv_sec = 0;
        ms.tv_nsec = 1000000;
        nanosleep (&ms, NULL);

        //  Initialize ZeroMQ
        zctx_t *context = zctx_new ();
        assert (context);
        void *socket = zsocket_new (context, ZMQ_REP);
        assert (socket);
        assert (streq (zsocket_type_str (socket), "REP"));
        int rc = zsocket_bind (socket, "tcp://*:%d", port);
        if (rc != port) {
                printf ("E: bind failed: %s\n", strerror (errno));
                exit (EXIT_FAILURE);
        }

        //  Start remembering the last timer tick
        uint64_t ts = 0;
        uint64_t last_ts = 0;
        uint64_t seq = 0;

        //  Main loop
        s_catch_signals ();        
        while (1) {
                //  Wait for the next request
                zmsg_t *request_msg = zmsg_new ();
                assert (request_msg);
                request_msg = zmsg_recv (socket);
                assert (request_msg);
                zmsg_destroy (&request_msg);

                //  Grab a time click
                last_ts = ts;
                ts = get_ts ();

                //  Make sure the system clock wasn't reversed on us
                if (ts < last_ts) {
                        //  Wait until it catches up
                        while (ts <= last_ts) {
                                nanosleep (&ms, NULL);
                                ts = get_ts ();
                        }
                }

                //  Increment the sequence number
                if (ts != last_ts) {
                        //  We're in a new time click, so reset the sequence
                        seq = 0;
                }
                else if (seq == SEQ_MAX) {
                        //  Wrapped sequence, so wait for the next time tick
                        seq = 0;
                        nanosleep (&ms, NULL);
                }
                else {
                        //  Still in the same time click
                        seq++;
                }

                //  Build the ID and put it in network byte order
                uint64_t id = build_id (ts, machine, seq);
                uint64_t id_be64 = htobe64 (id);

                //  Reply
                zmsg_t *reply_msg = zmsg_new ();
                assert (reply_msg);
                zframe_t *frame = zframe_new (&id_be64, 8);
                assert (frame);
                zmsg_push (reply_msg, frame);
                assert (zmsg_size (reply_msg) == 1);
                assert (zmsg_content_size (reply_msg) == 8);
                zmsg_send (&reply_msg, socket);
                assert (reply_msg == NULL);

                //  Exit program
                if (s_interrupted) {
                        printf ("interrupt received, killing server…\n");
                        break;
                }
        }
        zctx_destroy (&context);
        if (has_daemonize_opt) {
                if (pid_file > 0) {
                        unlink (pid_file_path);
                        close (pid_file);
                }
        }
        exit (EXIT_SUCCESS);
}