Esempio n. 1
0
/** Create a BufferedWriter instance
 *
 * \param outStream opaque OmlOutStream handler
 * \param queueCapacity maximal size [B] of the internal queue queueCapaity/chunkSize will be used (at least 2)
 * \param chunkSize size [B] of buffer space allocated at a time, set to 0 for default (DEF_CHAIN_BUFFER_SIZE)
 * \return an instance pointer if successful, NULL otherwise
 *
 * \see DEF_CHAIN_BUFFER_SIZE
 */
BufferedWriter*
bw_create(OmlOutStream* outStream, long  queueCapacity, long chunkSize)
{
  long nchunks;
  BufferedWriter* self = NULL;

  assert(outStream>=0);
  assert(queueCapacity>=0);
  assert(chunkSize>=0);

  if((self = (BufferedWriter*)oml_malloc(sizeof(BufferedWriter)))) {
    memset(self, 0, sizeof(BufferedWriter));

    self->outStream = outStream;
    /* This forces a 'connected' INFO message upon first connection */
    self->backoff = 1;

    self->bufSize = chunkSize > 0 ? chunkSize : DEF_CHAIN_BUFFER_SIZE;

    nchunks = queueCapacity / self->bufSize;
    self->unallocatedBuffers = (nchunks > 2) ? nchunks : 2; /* at least two chunks */

    logdebug ("%s: Buffer size %dB (%d chunks of %dB)\n",
        self->outStream->dest,
        self->unallocatedBuffers*self->bufSize,
        self->unallocatedBuffers, self->bufSize);

    if(NULL == (self->writerChunk = self->nextReaderChunk = self->firstChunk = createBufferChunk(self))) {
      oml_free(self);
      self = NULL;

    } else if(NULL == (self->meta_buf = mbuf_create())) {
      destroyBufferChain(self);
      oml_free(self);
      self = NULL;

    } else if(NULL == (self->read_buf = mbuf_create())) {
      destroyBufferChain(self);
      oml_free(self);
      self = NULL;

    } else {
      /* Initialize mutex and condition variable objects */
      pthread_cond_init(&self->semaphore, NULL);
      pthread_mutex_init(&self->lock, NULL);
      logdebug3("%s: initialised mutex %p\n", self->outStream->dest, &self->lock);
      pthread_mutex_init(&self->meta_lock, NULL);
      logdebug3("%s: initialised mutex %p\n", self->outStream->dest, &self->meta_lock);

      /* Initialize and set thread detached attribute */
      pthread_attr_t tattr;
      pthread_attr_init(&tattr);
      pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
      self->active = 1;
      pthread_create(&self->readerThread, &tattr, bufferedWriterThread, (void*)self);
    }
  }

  return (BufferedWriter*)self;
}
Esempio n. 2
0
void
client_free (Client *client)
{
  if (client == NULL) return;

  if (client->file) {
    fflush (client->file);
    fclose (client->file);
    client->file = NULL;
  }

  oml_free (client->file_name);
  oml_free (client->downstream_addr);

  struct header *header = client->headers;

  while (header) {
    struct header *next = header->next;
    header_free (header);
    header = next;
  }

  msg_queue_destroy (client->messages);
  cbuf_destroy (client->cbuf);

  pthread_cond_destroy (&client->condvar);
  pthread_mutex_destroy (&client->mutex);

  socket_free (client->recv_socket);

  oml_free (client);
}
Esempio n. 3
0
/** Terminate the Socket and free its allocated memory.
 *
 * If the socket is still open, it will be closed.
 *
 * \param socket Socket to free
 * \see socket_new, socket_close
 */
void
socket_free (Socket* socket)
{
  SocketInt* self = (SocketInt *)socket;
  socket_close(socket);
  if (self->name) { oml_free(self->name); }
  if (self->dest) { oml_free(self->dest); }
  if (self->service) { oml_free(self->service); }
  if (self->results) { freeaddrinfo(self->results); }
  oml_free (self);
}
Esempio n. 4
0
/** Deallocate a TableDescr array
 *
 * \param tables beginning of the array
 * \param n size of the array
 */
void
table_descr_array_free (TableDescr* tables, int n)
{
  int i = 0;
  for (i = 0; i < n; i++) {
      oml_free (tables[i].name);
      if (tables[i].schema) {
        schema_free (tables[i].schema);
      }
  }

  oml_free(tables);
}
Esempio n. 5
0
/** Find a database instance for name.
 *
 * If no database with this name exists, a new one is created.
 *
 * \param name name of the database to find
 * \return a pointer to the database
 */
Database*
database_find (const char* name)
{
  Database* db = first_db;
  while (db != NULL) {
    if (!strcmp(name, db->name)) {
      loginfo ("%s: Database already open (%d client%s)\n",
                name, db->ref_count, db->ref_count>1?"s":"");
      db->ref_count++;
      return db;
    }
    db = db->next;
  }

  // need to create a new one
  Database *self = oml_malloc(sizeof(Database));
  logdebug("%s: Creating or opening database\n", name);
  strncpy(self->name, name, MAX_DB_NAME_SIZE);
  self->ref_count = 1;
  self->create = database_create_function (dbbackend);

  if (self->create (self)) {
    oml_free(self);
    return NULL;
  }

  if (database_init (self) == -1) {
    database_release(self);
    oml_free (self);
    return NULL;
  }

  char *start_time_str = self->get_metadata (self, "start_time");

  if (start_time_str == NULL) {
    /* No start time: this is probably a new database */
    database_hook_send_event(self, HOOK_CMD_DBCREATED);

  } else {
    database_hook_send_event(self, HOOK_CMD_DBOPENED);
    self->start_time = strtol (start_time_str, NULL, 0);
    oml_free (start_time_str);
    logdebug("%s: Retrieved start-time = %lu\n", name, self->start_time);
  }

  // hook this one into the list of active databases
  self->next = first_db;
  first_db = self;

  return self;
}
Esempio n. 6
0
/** Unregister all built-in filters.
 */
void unregister_filters ()
{
  FilterType* ft = filter_types;
  logdebug("Unregistering filters\n");

  while(ft) {
    filter_types = ft->next;

    oml_free(ft->definition);
    oml_free(ft);

    ft = filter_types;
  };
}
Esempio n. 7
0
/** Deallocate a TableDescr linked list
 *
 * Also free the encapsulated schema structures.
 *
 * \param tables head of the list
 */
void
table_descr_list_free (TableDescr* tables)
{
  TableDescr* t = tables;

  while (t) {
      TableDescr* next = t->next;
      oml_free (t->name);
      if (t->schema) {
        schema_free (t->schema);
      }
      oml_free (t);
      t = next;
  }
}
Esempio n. 8
0
/** Destroy the Buffer chain of a BufferedWriter
 *
 * \param self pointer to the BufferedWriter
 *
 * \return 0 on success, or a negative number otherwise
 */
int
destroyBufferChain(BufferedWriter* self) {
  BufferChunk *chunk, *start;

  if (!self) {
    return -1;
  }

  /* BufferChunk is a circular buffer */
  start = self->firstChunk;
  while( (chunk = self->firstChunk) && chunk!=start) {
    logdebug("Destroying BufferChunk at %p\n", chunk);
    self->firstChunk = chunk->next;

    mbuf_destroy(chunk->mbuf);
    pthread_mutex_destroy(&chunk->lock);
    oml_free(chunk);
  }

  mbuf_destroy(self->meta_buf);
  mbuf_destroy(self->read_buf);

  pthread_cond_destroy(&self->semaphore);
  pthread_mutex_destroy(&self->meta_lock);
  pthread_mutex_destroy(&self->lock);

  return 0;
}
Esempio n. 9
0
/** Deallocate memory for a TimerInt
 * \param timer TimerInt to deallocate
 * \see eventloop_every, eventloop_timer_stop
 */
static void eventloop_timer_free(TimerInt* timer) {
  if (!timer) {
    o_log(O_LOG_DEBUG, "EventLoop: %s: Trying to free NULL pointer\n", __FUNCTION__);
  } else {
    oml_free(timer);
  }
}
Esempio n. 10
0
/** Called to write into the socket
 * \see oml_outs_write_f
 *
 * If the connection needs to be re-established, header is sent first, then buffer,
 *
 * \see \see open_socket, socket_write
 */
static ssize_t
net_stream_write(OmlOutStream* hdl, uint8_t* buffer, size_t  length, uint8_t* header, size_t  header_length)
{
    OmlNetOutStream* self = (OmlNetOutStream*)hdl;
    size_t count;

    /* The header can be NULL, but header_length MUST be 0 in that case */
    assert(header || !header_length);

    /* Initialise the socket the first time */
    while (self->socket == NULL) {
        logdebug ("%s: Connecting to server\n", self->dest);
        if (!open_socket(self)) {
            logdebug("%s: Connection attempt failed\n", self->dest);
            return 0;
        }
    }

    /* If the underlying socket has registered a disconnection, it will reconnect on its own
     * however, we need to check it to make sure we send the headers before anything else */
    if(socket_is_disconnected(self->socket)) {
        self->header_written = 0;
    }

    out_stream_write_header(hdl, socket_write, header, header_length);

    if(o_log_level_active(O_LOG_DEBUG4)) {
        char *out = to_octets(buffer, length);
        logdebug("%s: Sending data %s\n", self->dest, out);
        oml_free(out);
    }
    count = socket_write(hdl, buffer, length);
    return count;
}
Esempio n. 11
0
void
msg_queue_destroy (struct msg_queue *queue)
{
    while (queue->length > 0)
        msg_queue_remove (queue);
    oml_free (queue);
}
Esempio n. 12
0
/** Close an OmlFileOutStream's output file
 * \param hdl pointer to the OmlFileOutStream
 * \return amount of data written, or -1 on error
 */
static int
file_stream_close(OmlOutStream* hdl)
{
  OmlFileOutStream* self = (OmlFileOutStream*)hdl;
  int ret = -1;

  logdebug("Destroying OmlFileOutStream to file %s at %p\n", self->dest, self);

  if (self->f != NULL) {
    ret = fclose(self->f);
    self->f = NULL;
  }
  oml_free(self->dest);
  oml_free(self);
  return ret;
}
Esempio n. 13
0
/** Close an output stream and destroy the objects.
 *
 * \param instance handle (i.e., pointer) to a BufferedWriter
 */
void
bw_close(BufferedWriter* instance)
{
  int *retval;
  BufferedWriter *self = (BufferedWriter*)instance;

  if(!self) { return; }

  if (oml_lock (&self->lock, __FUNCTION__)) { return; }
  self->active = 0;

  loginfo ("%s: Waiting for buffered queue thread to drain...\n", self->outStream->dest);

  pthread_cond_signal (&self->semaphore);
  oml_unlock (&self->lock, __FUNCTION__);

  if(pthread_join (self->readerThread, (void**)&retval)) {
    logwarn ("%s: Cannot join buffered queue reader thread: %s\n",
        self->outStream->dest, strerror(errno));

  } else {
    if (1 == *retval) {
      logdebug ("%s: Buffered queue fully drained\n", self->outStream->dest);
    } else {
      logerror ("%s: Buffered queue did not fully drain\n",
          self->outStream->dest, *retval);
    }
  }

  self->outStream->close(self->outStream);
  destroyBufferChain(self);
  oml_free(self);
}
Esempio n. 14
0
/** Called to close the socket
 * \see oml_outs_close_f
 */
static int
net_stream_close(OmlOutStream* stream)
{
    OmlNetOutStream* self = (OmlNetOutStream*)stream;

    logdebug("%s: Destroying OmlNetOutStream at %p\n", self->dest, self);

    if (self->socket != 0) {
        socket_close(self->socket);
        self->socket = NULL;
    }
    oml_free(self->dest);
    oml_free(self->host);
    oml_free(self->protocol);
    oml_free(self->service);
    oml_free(self);
    return 0;
}
Esempio n. 15
0
int
main(int argc, const char *argv[])
{
  int c, i, ret;

  /* Reconstruct command line */
  size_t cmdline_len = 0;
  for(i = 0; i < argc; i++) {
    cmdline_len += strlen(argv[i]) + 1;
  }
  char *cmdline = oml_malloc(cmdline_len);
  cmdline[0] = '\0';
  for(i = 0; i < argc; i++) {
    strncat(cmdline, argv[i], cmdline_len);
    cmdline_len -= strlen(argv[i]);
    strncat(cmdline, " ", cmdline_len);
    cmdline_len--;
  }

  /* Initialize OML */
  if((ret = omlc_init("generator", &argc, argv, NULL)) < 0) {
    logerror("Could not initialise OML\n");
    return -1;
  }

  /* Parse command line arguments */
  poptContext optCon = poptGetContext(NULL, argc, argv, options, 0); /* options is defined in generator_popt.h */
  while ((c = poptGetNextOpt(optCon)) > 0) {}

  /* Initialise measurement points and start OML */
  oml_register_mps(); /* Defined in generator_oml.h */
  if(omlc_start()) {
    logerror("Could not start OML\n");
    return -1;
  }

  /* Inject some metadata about this application */
  OmlValueU v;
  omlc_zero(v);
  omlc_set_string(v, PACKAGE_NAME);
  omlc_inject_metadata(NULL, "appname", &v, OML_STRING_VALUE, NULL);

  omlc_set_string(v, PACKAGE_VERSION);
  omlc_inject_metadata(NULL, "version", &v, OML_STRING_VALUE, NULL);

  omlc_set_string(v, cmdline);
  omlc_inject_metadata(NULL, "cmdline", &v, OML_STRING_VALUE, NULL);
  omlc_reset_string(v);
  oml_free(cmdline);

  /* Inject measurements */
  run(g_opts, g_oml_mps_generator); /* Do some work and injections, see above */

  omlc_close();

  return 0;
}
Esempio n. 16
0
/** Terminate Channel and free its allocated memory
 *
 * The file descriptor in ch->socket is *NOT* cleaned up here, as all Channels are created through eventloop_on_* functions which first argument is a Socket, socket or file descriptor. The caller of these functions is in charge of cleaning
 *
 * \param ch Channel to terminate and free
 *
 * \see channel_new
 * \see oml_free
 */
static void channel_free(
    Channel *ch
) {
  if (!ch) {
    o_log(O_LOG_DEBUG, "EventLoop: %s: Trying to free NULL pointer\n", __FUNCTION__);
  } else {
    oml_free(ch);
  }
}
Esempio n. 17
0
/** Destroy a filter and free its memory.
 *
 * This function is designed so it can be used in a while loop to clean up the
 * entire linked list:
 *
 *   while( (f=destroy_ms(f)) );
 *
 * \param f pointer to the filter to destroy
 * \returns f->next (can be NULL)
 */
OmlFilter *destroy_filter(OmlFilter* f) {
  OmlFilter *next;
  if (!f)
    return NULL;

  logdebug("Destroying filter %s at %p\n", f->name, f);

  next = f->next;

  if(f->result) {
    oml_value_array_reset(f->result, f->output_count);
    oml_free(f->result);
  }
  if(f->instance_data)
    oml_free(f->instance_data);
  oml_free(f);

  return next;
}
Esempio n. 18
0
/*
 * Destroy a table in a database, by free all allocated data
 * structures.  Does not release the table in the backend adapter.
 */
void
database_table_free(Database *database, DbTable *table)
{
  if (database && table) {
    logdebug("%s: Freeing table '%s'\n", database->name, table->schema->name);
    schema_free (table->schema);
    oml_free(table);
  } else {
    logwarn("%s: Tried to free a NULL table (or database was NULL).\n",
            (database ? database->name : "NONE"));
  }
}
Esempio n. 19
0
/** Create the adapter structure for a table.
 *
 * Create a new table in the database, with given schema.  Register
 * the table with the database, so that database_find_table () will
 * find it. Return a pointer to the table, or NULL on error.
 *
 * The schema is deep copied, so the caller can safely free the
 * schema.
 *
 * Note: this function does NOT issue the SQL required to create the
 * table in the actual storage backend.
 *
 * \param database Database to add the DbTable to
 * \param schema schema structure for that tables
 * \return an oml_malloc'd DbTable (already added to database), or NULL on error
 *
 * \see database_find_table, schema_copy, database_release
 */
DbTable*
database_create_table (Database *database, const struct schema *schema)
{
  DbTable *table = oml_malloc (sizeof (DbTable));
  if (!table)
    return NULL;
  table->schema = schema_copy (schema);
  if (!table->schema) {
    oml_free (table);
    return NULL;
  }
  table->next = database->first_table;
  database->first_table = table;
  return table;
}
Esempio n. 20
0
/** Eventloop callback called when a new connection is received on a listening Socket.
 *
 * This function accept()s the connection, and creates a SocketInt to wrap
 * the underlying system socket. It then runs the user-supplied callback
 * (passed to socket_server_new() when creating the listening Socket) on this
 * new object, passing it the handle (passed to socket_server_new( too))
 *
 * \param source source from which the event was received (e.g., an OComm Channel)
 * \param handle pointer to opaque data passed when creating the listening Socket
 */
static void
on_client_connect(SockEvtSource* source, void* handle)
{
  (void)source; // FIXME: Check why source parameter is unused
  char host[ADDRLEN], serv[SERVLEN];
  size_t namesize;
  *host = 0;
  *serv = 0;

  socklen_t cli_len;
  SocketInt* self = (SocketInt*)handle;
  SocketInt* newSock = socket_initialize(NULL);
  cli_len = sizeof(newSock->servAddr.sa_stor);
  newSock->sockfd = accept(self->sockfd,
                &newSock->servAddr.sa,
                 &cli_len);

  if (newSock->sockfd < 0) {
    o_log(O_LOG_ERROR, "socket(%s): Error on accept: %s\n",
          self->name, strerror(errno));
    oml_free(newSock);
    return;
  }

  /* XXX: Duplicated somewhat with socket_in_new and s_connect */
  if (!getnameinfo(&newSock->servAddr.sa, cli_len,
        host, ADDRLEN, serv, SERVLEN,
        NI_NUMERICHOST|NI_NUMERICSERV)) {
    namesize =  strlen(host) + strlen(serv) + 3 + 1;
    newSock->name = oml_realloc(newSock->name, namesize);
    snprintf(newSock->name, namesize, "[%s]:%s", host, serv);

  } else {
    namesize =  strlen(host) + 4 + 10 + 1; /* XXX: 10 is arbitrarily chosen for the
                                              number of characters in sockfd's decimal
                                              representation */
    newSock->name = oml_realloc(newSock->name, namesize);
    snprintf(newSock->name, namesize, "%s-io:%d", self->name, newSock->sockfd);
    o_log(O_LOG_WARN, "socket(%s): Error resolving new client source, defaulting to %s: %s\n",
        self->name, newSock->name, strerror(errno));
  }

  if (self->connect_callback) {
    self->connect_callback((Socket*)newSock, self->connect_handle);
  }
}
Esempio n. 21
0
/** Function called to close the writer and free its allocated objects.
 * \see oml_writer_close
 */
static OmlWriter*
owb_close(OmlWriter* writer)
{
  OmlWriter *next;

  if(!writer) {
    return NULL;
  }

  OmlBinWriter *self = (OmlBinWriter*) writer;

  next = self->next;

  // Blocks until the buffered writer drains
  bw_close (self->bufferedWriter);
  oml_free(self);

  return next;
}
Esempio n. 22
0
/** One client no longer uses this database.
 * If this was the last client checking out, close database.
 * \param self the database to release
 * \see db_adapter_release
 */
void
database_release(Database* self)
{
  if (self == NULL) {
    logerror("NONE: Trying to release a NULL database.\n");
    return;
  }
  if (--self->ref_count > 0) return; // still in use

  // unlink DB
  Database* db_p = first_db;
  Database* prev_p = NULL;
  while (db_p != NULL && db_p != self) {
    prev_p = db_p;
    db_p = db_p->next;
  }
  if (db_p == NULL) {
    logerror("%s:  Trying to release an unknown database\n", self->name);
    return;
  }
  if (prev_p == NULL)
    first_db = self->next; // was first
  else
    prev_p->next = self->next;

  // no longer needed
  DbTable* t_p = self->first_table;
  while (t_p != NULL) {
    DbTable* t = t_p->next;
    /* Release the backend storage for this table */
    self->table_free (self, t_p);
    /* Release the table */
    database_table_free(self, t_p);
    t_p = t;
  }

  loginfo ("%s: Closing database\n", self->name);
  self->release (self);

  database_hook_send_event(self, HOOK_CMD_DBCLOSED);

  oml_free(self);
}
Esempio n. 23
0
/** Remove the node at the head of the queue.  This operation is O(1).
 */
void
msg_queue_remove (struct msg_queue *queue)
{
    if (queue == NULL || queue->tail == NULL)
        return;

    struct msg_queue_node *head = queue->tail->next;

    assert (head != NULL);

    /* Unlink the head */
    queue->length--;
    if (queue->length == 0)
        queue->tail = NULL;
    else
        queue->tail->next = head->next;

    oml_free (head);
}
Esempio n. 24
0
/** Create a new table description
 *
 * The caller should oml_free the returned value when no longer needed.
 * The schema argument is kept verbatim (no copy). XXX: It should be copied internally.
 *
 * \param name name of the table
 * \param schema MP schema of the table
 * \return an oml_malloc'd TableDescr, or NULL on error
 * \see oml_malloc, oml_free
 */
TableDescr*
table_descr_new (const char* name, struct schema* schema)
{
  if (name == NULL)
    return NULL;

  /* schema == NULL means metadata table */

  char *new_name = oml_strndup (name, strlen (name));

  TableDescr* t = oml_malloc (sizeof(TableDescr));
  if (t == NULL) {
    oml_free (new_name);
    return NULL;
  }
  t->name = new_name;
  t->schema = schema;
  t->next = NULL;

  return t;
}
Esempio n. 25
0
/** Try to convert a string to the given OmlValueT and store it an OmlValueU.
 *
 * Storage for value should have already been cleared (e.g., with
 * oml_value_set_type(), oml_value_reset() omlc_reset_string() or
 * omlc_reset_blob() if appropriate).
 *
 * Assumes the destination OmlValueU has been properly reset.
 *
 * \param value pointer to output OmlValue
 * \param type type of data to get from the string
 * \param value_s input string
 * \return  0 on success, -1 otherwise (e.g., conversion error)
 * \see oml_value_from_s, oml_value_from_typed_s
 * \see oml_value_set_type, oml_value_reset, omlc_reset_string, omlc_reset_blob
 */
static int
oml_value_ut_from_s (OmlValueU *value, OmlValueT type, const char *value_s)
{
    char *s, *eptr;
    ssize_t n;
    size_t s_sz, blob_sz, nof_elts, bytes;
    uint8_t *blob;
    oml_guid_t c;
    char *p;
    char *q;

    errno = 0; /* Not all paths manipulate errno, so make sure its value is reset */

    switch (type) {
    case OML_LONG_VALUE:
        logwarn("%s(): OML_LONG_VALUE is deprecated, please use OML_INT32_VALUE instead\n", __FUNCTION__);
        omlc_set_long (*value, strtol (value_s, NULL, 0));
        break;

    case OML_INT32_VALUE:
        omlc_set_int32 (*value, strtol (value_s, NULL, 0));
        break;
    case OML_UINT32_VALUE:
        omlc_set_uint32 (*value, strtoul (value_s, NULL, 0));
        break;
    case OML_INT64_VALUE:
        omlc_set_int64 (*value, strtoll (value_s, NULL, 0));
        break;
    case OML_UINT64_VALUE:
        omlc_set_uint64 (*value, strtoull (value_s, NULL, 0));
        break;
    case OML_DOUBLE_VALUE:  {
        omlc_set_double (*value, strtod (value_s, &eptr));
        if (eptr == value_s) {
            omlc_set_double (*value, NAN);
        }
        break;
    }
    case OML_STRING_VALUE:
        s = oml_malloc(strlen(value_s)+1);
        n = backslash_decode(value_s, s);
        omlc_reset_string(*value);
        omlc_set_string(*value, s);
        omlc_set_string_size(*value,n+1);
        break;

    case OML_DATETIME_VALUE:
        s = oml_malloc(strlen(value_s)+1);
        n = backslash_decode(value_s, s);
        omlc_reset_string(*value);
        omlc_set_string(*value, s);
        omlc_set_string_size(*value,n+1);
        break;

    case OML_BLOB_VALUE:
        omlc_reset_blob(*value);
        s_sz = base64_validate_string(value_s);
        if(s_sz != -1) {
            blob_sz = base64_size_blob(s_sz);
            blob = oml_malloc(blob_sz);
            base64_decode_string(s_sz, value_s, blob_sz, blob);
            omlc_set_blob_ptr(*value, blob);
            omlc_set_blob_length(*value, blob_sz);
            omlc_set_blob_size(*value, blob_sz);
        }
        break;

    case OML_GUID_VALUE:
        omlc_string_to_guid(value_s, &c);
        omlc_set_guid(*value, c);
        break;

    case OML_BOOL_VALUE:
        omlc_set_bool(*value, oml_value_string_to_bool(value_s));
        break;

    case OML_VECTOR_DOUBLE_VALUE:
        omlc_reset_vector(*value);
        nof_elts = strtod(value_s, &p);
        if(p - value_s) {
            size_t i, bytes;
            double *elts = oml_calloc(nof_elts, sizeof(double));
            if(elts) {
                for(i = 0; i < nof_elts; i++) {
                    elts[i] = strtod(p, &q);
                    if(q - p)
                        p = q;
                    else {
                        oml_free(elts);
                        logerror("%s(): bad [double] vector element '%s'\n", __FUNCTION__, p);
                        return -1;
                    }
                }
                bytes = nof_elts * sizeof(double);
                omlc_set_vector_ptr(*value, elts);
                omlc_set_vector_length(*value, bytes);
                omlc_set_vector_size(*value, bytes);
                omlc_set_vector_nof_elts(*value, nof_elts);
                omlc_set_vector_elt_size(*value, sizeof(double));
            } else {
                logerror("%s(): out of memory reading [double] of size %zu\n", __FUNCTION__, nof_elts);
                return -1;
            }
        } else {
            logerror("%s(): bad [double] size '%s'\n", __FUNCTION__, value_s);
            return -1;
        }
        break;

    case OML_VECTOR_INT32_VALUE:
        omlc_reset_vector(*value);
        nof_elts = strtol(value_s, &p, 0);
        if(p - value_s) {
            size_t i;
            int32_t *elts = oml_calloc(nof_elts, sizeof(int32_t));
            if(elts) {
                for(i = 0; i < nof_elts; i++) {
                    elts[i] = strtol(p, &q, 0);
                    if(q - p)
                        p = q;
                    else {
                        oml_free(elts);
                        logerror("%s(): bad [int32] vector element '%s'\n", __FUNCTION__, p);
                        return -1;
                    }
                }
                bytes = nof_elts * sizeof(int32_t);
                omlc_set_vector_ptr(*value, elts);
                omlc_set_vector_length(*value, bytes);
                omlc_set_vector_size(*value, bytes);
                omlc_set_vector_nof_elts(*value, nof_elts);
                omlc_set_vector_elt_size(*value, sizeof(int32_t));
            } else {
                logerror("%s(): out of memory reading [int32] of size %zu\n", __FUNCTION__, nof_elts);
                return -1;
            }
        } else {
            logerror("%s(): bad [int32] size '%s'\n", __FUNCTION__, value_s);
            return -1;
        }
        break;

    case OML_VECTOR_UINT32_VALUE:
        omlc_reset_vector(*value);
        nof_elts = strtoul(value_s, &p, 0);
        if(p - value_s) {
            size_t i;
            uint32_t *elts = oml_calloc(nof_elts, sizeof(uint32_t));
            if(elts) {
                for(i = 0; i < nof_elts; i++) {
                    elts[i] = strtoul(p, &q, 0);
                    if(q - p)
                        p = q;
                    else {
                        oml_free(elts);
                        logerror("%s(): bad [uint32] vector element '%s'\n", __FUNCTION__, p);
                        return -1;
                    }
                }
                bytes = nof_elts * sizeof(uint32_t);
                omlc_set_vector_ptr(*value, elts);
                omlc_set_vector_length(*value, bytes);
                omlc_set_vector_size(*value, bytes);
                omlc_set_vector_nof_elts(*value, nof_elts);
                omlc_set_vector_elt_size(*value, sizeof(uint32_t));
            } else {
                logerror("%s(): out of memory reading [uint32] of size %zu\n", __FUNCTION__, nof_elts);
                return -1;
            }
        } else {
            logerror("%s(): bad [uint32] size '%s'\n", __FUNCTION__, value_s);
            return -1;
        }
        break;

    case OML_VECTOR_INT64_VALUE:
        omlc_reset_vector(*value);
        nof_elts = strtoll(value_s, &p, 0);
        if(p - value_s) {
            size_t i;
            int64_t *elts = oml_calloc(nof_elts, sizeof(int64_t));
            if(elts) {
                for(i = 0; i < nof_elts; i++) {
                    elts[i] = strtoll(p, &q, 0);
                    if(q - p)
                        p = q;
                    else {
                        oml_free(elts);
                        logerror("%s(): bad [int64] vector element '%s'\n", __FUNCTION__, p);
                        return -1;
                    }
                }
                bytes = nof_elts * sizeof(int64_t);
                omlc_set_vector_ptr(*value, elts);
                omlc_set_vector_length(*value, bytes);
                omlc_set_vector_size(*value, bytes);
                omlc_set_vector_nof_elts(*value, nof_elts);
                omlc_set_vector_elt_size(*value, sizeof(int64_t));
            } else {
                logerror("%s(): out of memory reading [int64] of size %zu\n", __FUNCTION__, nof_elts);
                return -1;
            }
        } else {
            logerror("%s(): bad [int64] size '%s'\n", __FUNCTION__, value_s);
            return -1;
        }
        break;

    case OML_VECTOR_UINT64_VALUE:
        omlc_reset_vector(*value);
        nof_elts = strtoull(value_s, &p, 0);
        if(p - value_s) {
            size_t i;
            uint64_t *elts = oml_calloc(nof_elts, sizeof(uint64_t));
            if(elts) {
                for(i = 0; i < nof_elts; i++) {
                    elts[i] = strtoull(p, &q, 0);
                    if(q - p)
                        p = q;
                    else {
                        oml_free(elts);
                        logerror("%s(): bad [uint64] vector element '%s'\n", __FUNCTION__, p);
                        return -1;
                    }
                }
                bytes = nof_elts * sizeof(uint64_t);
                omlc_set_vector_ptr(*value, elts);
                omlc_set_vector_length(*value, bytes);
                omlc_set_vector_size(*value, bytes);
                omlc_set_vector_nof_elts(*value, nof_elts);
                omlc_set_vector_elt_size(*value, sizeof(uint64_t));
            } else {
                logerror("%s(): out of memory reading [uint64] of size %zu\n", __FUNCTION__, nof_elts);
                return -1;
            }
        } else {
            logerror("%s(): bad [uint64] size '%s'\n", __FUNCTION__, value_s);
            return -1;
        }
        break;

    case OML_VECTOR_BOOL_VALUE:
        omlc_reset_vector(*value);
        nof_elts = strtoul(value_s, &p, 0);
        if(p - value_s) {
            char *n;
            size_t i;
            bool *elts = oml_calloc(nof_elts, sizeof(bool));
            if(elts) {
                for(i = 0; i < nof_elts; i++) {
                    char *v = strtok_r(p, " ", &n);
                    if(v) {
                        elts[i] = strncasecmp(v, "false", strlen(v));
                        p = n;
                    } else {
                        oml_free(elts);
                        logerror("%s(): bad [bool] '%s'\n", __FUNCTION__, p);
                        return -1;
                    }
                }
                omlc_set_vector_bool(*value, elts, nof_elts);
                bytes = nof_elts * sizeof(bool);
                omlc_set_vector_ptr(*value, elts);
                omlc_set_vector_length(*value, bytes);
                omlc_set_vector_size(*value, bytes);
                omlc_set_vector_nof_elts(*value, nof_elts);
                omlc_set_vector_elt_size(*value, sizeof(bool));
            } else {
                logerror("%s(): out of memory reading [bool] of size %zu\n", __FUNCTION__, nof_elts);
                return -1;
            }
        } else {
            logerror("%s(): bad [bool] size '%s'\n", __FUNCTION__, value_s);
            return -1;
        }
        break;

    default:
        logerror("%s() for type '%d' not implemented to convert '%s'\n", __FUNCTION__, type, value_s);
        return -1;
    }

    if (errno == ERANGE) {
        logerror("%s(): underflow or overlow converting value from string '%s'\n", __FUNCTION__, value_s);
        return -1;
    }

    return 0;
}
Esempio n. 26
0
/** Search a Database's registered DbTables for one matchng the given schema.
 *
 * If none is found, the table is created. If one is found, but the schema
 * differs, try to append a number to the name (up to MAX_TABLE_RENAME), create
 * that table, and update the schema.
 *
 * If the table search/creation is successful, the returned DbTable is already
 * added to the list of the Database.
 *
 * \param database Database to search
 * \param schema schema structure for the table to add
 * \return a newly created DbTable for that table, or NULL on error
 *
 * \see MAX_TABLE_RENAME, database_create_table
 */
DbTable*
database_find_or_create_table(Database *database, struct schema *schema)
{
  if (database == NULL) return NULL;
  if (schema == NULL) return NULL;

  DbTable *table = NULL;
  struct schema *s = schema_copy(schema);
  int i = 1;
  int diff = 0, tnlen;

  tnlen = strlen(schema->name);

  do {
    table = database_find_table (database, s->name);

    if (table) {
      diff = schema_diff (s, table->schema);
      if (!diff) {
        if(database->semantic){
          if (database->table_create (database, table, 0)) {
              logerror ("%s: Couldn't create table '%s'\n", database->name, schema->name);
            }
        }
        schema_free(s);
        return table;

      } else if (diff == -1) {
        logerror ("%s: Schema error table '%s'\n", database->name, s->name);
        logdebug (" One of the server schema %p or the client schema %p is probably NULL\n", s, table->schema);

      } else if (diff > 0) {
        logdebug ("%s: Schema differ for table '%s', at or after column %d\n",
            database->name, s->name, diff);
      }

      if (i == 1) {
        /* First time we need to increase the size */
        /* Add space for 2 characters and null byte, that is up to '_9', with MAX_TABLE_RENAME = 10 */
        s->name = oml_realloc(s->name, tnlen + 3);
        strncpy(s->name, schema->name, tnlen);
      }
      snprintf(&s->name[tnlen], 3, "_%d", ++i);
    }

  } while(table && diff && (i < MAX_TABLE_RENAME));

  if (table && diff) {
    logerror ("%s: Too many (>%d) tables named '%s_x', giving up. Please use the rename attribute of <mp /> tags.\n",
      database->name, MAX_TABLE_RENAME, schema->name);
    schema_free(s);
    return NULL;
  }

  if(i>1) {
    /* We had to change the table name*/
    logwarn("%s: Creating table '%s' for new stream '%s' with incompatible schema\n", database->name, s->name, schema->name);
    oml_free(schema->name);
    schema->name = oml_strndup(s->name, tnlen+3);
  }
  schema_free(s);

  /* No table by that name exists, so we create it */
  table = database_create_table (database, schema);
  if (!table)
    return NULL;
  if (database->table_create (database, table, 0)) {
    logerror ("%s: Couldn't create table '%s'\n", database->name, schema->name);
    /* Unlink the table from the experiment's list */
    DbTable* t = database->first_table;
    if (t == table)
      database->first_table = t->next;
    else {
      while (t && t->next != table)
        t = t->next;
      if (t && t->next)
        t->next = t->next->next;
    }
    database_table_free (database, table);
    return NULL;
  }
  return table;
}
Esempio n. 27
0
/** Create OSocket objects bound to name and service.
 *
 * This function binds the newly-created socket, but doesn't listen on it just
 * yet.  If name resolves to more than one AF, several sockets are created,
 * linked through their `next' field.
 *
 * \param name name of the object, used for debugging
 * \param node address or name to listen on; defaults to all if NULL
 * \param service symbolic name or port number of the service to bind to
 * \param is_tcp true if TCP, false for UDP XXX: This should be more generic
 * \return a pointer to a linked list of SocketInt objects, cast as Socket
 *
 * \see getaddrinfo(3)
 */
Socket*
socket_in_new(const char* name, const char* node, const char* service, int is_tcp)
{
  SocketInt *self = NULL, *list = NULL;
  char nameserv[SOCKNAMELEN], *namestr = NULL;
  size_t namestr_size;
  struct addrinfo hints, *results, *rp;
  int ret;

  *nameserv = 0;
  memset(&hints, 0, sizeof(struct addrinfo));

  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP; /* FIXME: We should check self->is_tcp */
  hints.ai_flags= AI_PASSIVE;
  int val = 1;

  if((ret=getaddrinfo(node, service, &hints, &results))) {
      o_log(O_LOG_ERROR, "socket(%s): Error resolving %s:%s: %s\n",
          name, node, service, gai_strerror(ret));
      return NULL;
  }

  for (rp = results; rp != NULL; rp = rp->ai_next) {
    sockaddr_get_name((sockaddr_t*)rp->ai_addr, rp->ai_addrlen, nameserv, SOCKNAMELEN);
    namestr_size = strlen(name) + strlen(nameserv + 2);
    namestr = oml_realloc(namestr, namestr_size);
    snprintf(namestr, namestr_size, "%s-%s", name, nameserv);
    o_log(O_LOG_DEBUG, "socket(%s): Binding to %s (AF %d, proto %d)\n",
        name, nameserv, rp->ai_family, rp->ai_protocol);

    if (NULL == (self = (SocketInt*)socket_new(namestr, is_tcp))) {
      o_log(O_LOG_WARN, "socket(%s): Could allocate Socket to listen on %s: %s\n",
          self->name, nameserv, strerror(errno));

    } else if(0 > (self->sockfd =
          socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol))) {
      /* It's OK if some AFs fail, we check that in the end */
      o_log(O_LOG_DEBUG, "socket(%s): Could not create socket to listen on %s: %s\n",
          self->name, nameserv, strerror(errno));
      socket_free((Socket*)self);

    } else if(0 != setsockopt(self->sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int))){
      o_log(O_LOG_WARN, "socket(%s): Could not set option SO_REUSEADDR on socket to listen on %s: %s\n",
          self->name, nameserv, strerror(errno));
      close(self->sockfd);
      /* XXX: Not optimal: we could reuse the Socket */
      socket_free((Socket*)self);

    } else if (0 != bind(self->sockfd, rp->ai_addr, rp->ai_addrlen)) {
      o_log(O_LOG_WARN, "socket(%s): Error binding socket to listen on %s: %s\n",
          self->name, nameserv, strerror(errno));
      close(self->sockfd);
      /* XXX: Not optimal: we could reuse the Socket */
      socket_free((Socket*)self);

    } else {
      /* The last connected AFs (hence less important according to GAI) are
       * now at the front, but it's not a big deal as we treat them all
       * equally (i.e, we're going to listen on them all */
      self->next = (Socket*)list;
      list = self;
      self = NULL;
    }

  }

  if (namestr) { oml_free(namestr); }
  freeaddrinfo(results);

  if (NULL == list) {
    o_log(O_LOG_ERROR, "socket(%s): Could not create any socket to listen on port %s\n",
        name, service);
  }

  return (Socket*)list;
}
Esempio n. 28
0
/** Parse a collection URI of the form [scheme:][host[:port]][/path].
 *
 * Either host or path are mandatory.
 *
 * If under-qualified, the URI scheme is assumed to be 'tcp', the port '3003',
 * and the rest is used as the host; path is invalid for a tcp URI (only valid
 * for file).
 *
 * \param uri string containing the URI to parse
 * \param scheme pointer to be updated to a string containing the selected scheme, to be oml_free()'d by the caller
 * \param host pointer to be updated to a string containing the host, to be oml_free()'d by the caller
 * \param port pointer to be updated to a string containing the port, to be oml_free()'d by the caller
 * \param path pointer to be updated to a string containing the path, to be oml_free()'d by the caller
 * \return 0 on success, -1 otherwise
 *
 * \see oml_strndup, oml_free, oml_uri_type, URI_RE, URI_RE_NGROUP
 */
int
parse_uri (const char *uri, const char **scheme, const char **host, const char **port, const char **path)
{
  static regex_t preg;
  static int preg_valid = 0;
  char error[80];
  size_t nmatch = URI_RE_NGROUP+1;
  regmatch_t pmatch[nmatch];
  int bracket_offset = 0;
  int ret;
  char *str;
  int len, authlen;

  assert(scheme);
  assert(host);
  assert(port);
  assert(path);

  *scheme = *host = *port = *path = NULL;

  /* XXX: static so we only compile it once, but we cannot free it */
  if (!preg_valid) {
    if((ret = regcomp(&preg, URI_RE, REG_EXTENDED))) {
      regerror(ret , &preg, error, sizeof(error));
      logerror("Unable to compile RE /%s/ for URI parsing: %s\n", URI_RE, error);
      return -1;
    }
    preg_valid = 1;
  }

  if ((ret = regexec(&preg, uri, nmatch, pmatch, 0))) {
      regerror(ret , &preg, error, sizeof(error));
      logerror("Unable to match uri '%s' against RE /%s/: %s\n", uri, URI_RE, error);
      return -1;
  }

  logdebug("URI '%s' parsed as scheme: '%s', host: '%s', port: '%s', path: '%s'\n",
      uri,
      (pmatch[URI_RE_SCHEME].rm_so>=0)?(uri+pmatch[URI_RE_SCHEME].rm_so):"(n/a)",
      (pmatch[URI_RE_HOST].rm_so>=0)?(uri+pmatch[URI_RE_HOST].rm_so):"(n/a)",
      (pmatch[URI_RE_PORT].rm_so>=0)?(uri+pmatch[URI_RE_PORT].rm_so):"(n/a)",
      (pmatch[URI_RE_PATH].rm_so>=0)?(uri+pmatch[URI_RE_PATH].rm_so):"(n/a)"
      );

  if (pmatch[URI_RE_SCHEME].rm_so >= 0) {
    *scheme = oml_strndup(uri+pmatch[URI_RE_SCHEME].rm_so,
        pmatch[URI_RE_SCHEME].rm_eo - pmatch[URI_RE_SCHEME].rm_so);
  }
  if (pmatch[URI_RE_HOST].rm_so >= 0) {
    /* Host may contain bracketted IP addresses, clean that up. */
    if ('[' == *(uri + pmatch[URI_RE_HOST].rm_so)) {
      if (']' != *(uri + pmatch[URI_RE_HOST].rm_eo - 1)) {
        logerror("Unbalanced brackets in host part of '%s' (%d %d): %c\n",
            uri,
            pmatch[URI_RE_HOST].rm_so,
            pmatch[URI_RE_HOST].rm_eo,
            uri + pmatch[URI_RE_HOST].rm_eo - 1);
        return -1;
      }
      bracket_offset += 1;
    }
    *host = oml_strndup(uri+pmatch[URI_RE_HOST].rm_so + bracket_offset,
        pmatch[URI_RE_HOST].rm_eo - pmatch[URI_RE_HOST].rm_so - 2 * bracket_offset);
  }
  if (pmatch[URI_RE_PORT].rm_so >= 0) {
    *port = oml_strndup(uri+pmatch[URI_RE_PORT].rm_so,
        pmatch[URI_RE_PORT].rm_eo - pmatch[URI_RE_PORT].rm_so);
  }
  if (pmatch[URI_RE_PATH].rm_so >= 0) {
    *path= oml_strndup(uri+pmatch[URI_RE_PATH].rm_so,
        pmatch[URI_RE_PATH].rm_eo - pmatch[URI_RE_PATH].rm_so);
    /*if(!strncmp(*path, "::", 2) ||
        oml_uri_is_network(oml_uri_type(*path))) {
      logwarn("Parsing URI '%s' as 'file:%s'\n", uri, *path);
    }*/
  }

  /* Fixup parsing inconsistencies (mainly due to optionality of //) so we don't break old behaviours */
  if (!(*scheme)) {
    *scheme = oml_strndup("tcp", 3);
  }
  if(oml_uri_is_network(oml_uri_type(*scheme))) {
    if(!(*host)) {
      logerror("Network URI '%s' does not contain host"
          " (did you forget to put literal IPv6 addresses in brackets?)'\n", uri);
      return -1;
    }
    if (pmatch[URI_RE_SCHEME].rm_so >= 0 && pmatch[URI_RE_HOST].rm_so >= 0 &&
        pmatch[URI_RE_AUTHORITY_WITH_SLASHES].rm_so == pmatch[URI_RE_AUTHORITY].rm_so) {
      logwarn("Network URI without a double slash before authority part is deprecated: '%s' should be '%s://%s%s%s'\n",
          uri, *scheme, *host, *port?":":"", *port?*port:"");
    }
    if(!(*port)) {
      *port = oml_strndup(DEF_PORT_STRING, sizeof(DEF_PORT_STRING));
    }

  } else if ((*host) && oml_uri_is_file(oml_uri_type(*scheme))) {
    /* We split the filename into host and path in a URI without host;
     * concatenate them back together, adding all the leading slashes that were initially present */
    authlen = len = pmatch[URI_RE_AUTHORITY_WITH_SLASHES].rm_eo - pmatch[URI_RE_AUTHORITY_WITH_SLASHES].rm_so;
    if (*path) { len += strlen(*path); }
    str = oml_malloc(len + 1);
    if (!str) {
      logerror("Memory error parsing URI '%s'\n", uri);
      return -1;
    }
    *str=0;
    strncat(str, uri+pmatch[URI_RE_AUTHORITY_WITH_SLASHES].rm_so, authlen);
    if (*path) {
      len -= authlen;
      strncat(str, *path, len);
    }
    oml_free((void*)*host);
    *host = NULL;
    oml_free((void*)*path);
    *path = str;

  }

  return 0;
}