/** 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; }
END_TEST START_TEST (test_text_read) { uint8_t buf [] = "0.123456\t1\t42\tabde\t3.1416\t111\nbleftover text for next line"; char meta [] = "1 mympstrm label:string pi:double fighter:uint32"; MBuffer *mbuf = mbuf_create(); struct oml_message msg; struct schema *schema = schema_from_meta (meta); OmlValue values[3]; oml_value_array_init(values, 3); bzero(&msg, sizeof(msg)); mbuf_write (mbuf, buf, sizeof(buf)); int result = text_read_msg_start (&msg, mbuf); fprintf (stderr, "STRM: %d\n", msg.stream); fprintf (stderr, "SEQN: %u\n", msg.seqno); fprintf (stderr, "TS : %f\n", msg.timestamp); fprintf (stderr, "LEN : %d\n", msg.length); fprintf (stderr, "COUNT: %d\n", msg.count); result = text_read_msg_values (&msg, mbuf, schema, values); result *= 42; oml_value_array_reset(values, 3); }
/** Create and initialise a +Client+ structure to represent a single client. * * \param client_sock the socket associated to the client transmission * (from libocomm). The client_sock should be attached to an active * client that has been accepted by the server socket. * * \param page_size the page size for the underlying memory store for * buffering received measurements. * \param file_name save measurements to a file with this name. * \param server_port the port of the downstream OML server * \param server_address the address of the downstream OML Server * * \return a new Client structure */ Client* client_new (Socket* client_sock, int page_size, char* file_name, int server_port, char* server_address) { Client* self = (Client *)oml_malloc(sizeof(Client)); memset(self, 0, sizeof(Client)); self->state = C_HEADER; self->downstream_port = server_port; self->downstream_addr = oml_strndup (server_address, strlen (server_address)); self->mbuf = mbuf_create (); self->headers = NULL; self->msg_start = dummy_read_msg_start; self->messages = msg_queue_create (); self->cbuf = cbuf_create (page_size); self->file = fopen(file_name, "wa"); self->file_name = oml_strndup (file_name, strlen (file_name)); self->recv_socket = client_sock; /* FIXME: Return value checking */ pthread_mutex_init (&self->mutex, NULL); pthread_cond_init (&self->condvar, NULL); return self; }
END_TEST START_TEST (test_bin_read) { /* DATA_P, count=1, stream=3, { LONG_T 42 } */ uint8_t buf [] = { 0xAA, 0xAA, 0x01, 0x00, 0x00, 0x3, 0x1, // count = 1, stream = 3 0x01, 0x00, 0x00, 0x00, 0x32, // LONG_T 50 0x02, 0x54, 0x00, 0x00, 0x00, 0x05, // DOUBLE_T 42.0 0x01, 0x00, 0x10, 0xF4, 0x47, // LONG_T 1111111 0x02, 0x54, 0x00, 0x00, 0x00, 0x05, // DOUBLE_T 42.0 0x04, 0x03, 'A', 'B', 'C' // STRING_T "ABC" }; char meta [] = "3 mympstrm id:long hitchhiker:double sesame:string"; MBuffer *mbuf = mbuf_create (); struct oml_message msg; struct schema *schema = schema_from_meta (meta); OmlValue values [3]; int result; oml_value_array_init(values, 3); bzero(&msg, sizeof(msg)); int size = sizeof (buf) - 5; uint16_t nv = htons (size); memcpy (buf + 3, &nv, 2); mbuf_write (mbuf, buf, sizeof (buf)); result = bin_read_msg_start (&msg, mbuf); fail_unless(result > 0, "Unable to start reading binary message"); fprintf (stderr, "---\n"); fprintf (stderr, "STRM: %d\n", msg.stream); fprintf (stderr, "SEQN: %u\n", msg.seqno); fprintf (stderr, "TS : %f\n", msg.timestamp); fprintf (stderr, "LEN : %d\n", msg.length); fprintf (stderr, "COUNT: %d\n", msg.count); result = bin_read_msg_values (&msg, mbuf, schema, values); int i = 0; for (i = 0; i < 3; i++) { char s[64]; oml_value_to_s (&values[i], s, 64); fprintf (stderr, "%s\n", s); } oml_value_array_reset(values, 3); }
/** * \fn BufferedWriterHdl* buffSocket_create(long queueCapacity) * \brief Create a BufferedWriter instance * \param queueCapaity the max. size of the internal queue * \param chunkSize the size of buffer space allocated at a time, set to 0 for default * \return an instance pointer if success, NULL if not. */ BufferedWriterHdl bw_create( oml_outs_write_f writeFunc, //! Function to drain buffer - can block OmlOutStream* writeFuncHdl, //! Opaque handler to above function long queueCapacity, /* size of queue before dropping stuff */ long chunkSize ) { BufferedWriter* self = (BufferedWriter*)xmalloc(sizeof(BufferedWriter)); if (self ==NULL) return NULL; memset(self, 0, sizeof(BufferedWriter)); self->writeFunc = writeFunc; self->writeFuncHdl = writeFuncHdl; long bufSize = chunkSize > 0 ? chunkSize : DEF_CHAIN_BUFFER_SIZE; self->chainLength = bufSize; long chunks = queueCapacity / bufSize; self->chainsAvailable = chunks > 2 ? chunks : 2; /* at least two chunks */ /* Start out with two circular linked buffers */ BufferChain* buf1 = self->firstChain = createBufferChain(self); buf1->next = buf1; // BufferChain* buf2 = buf1->next = createBufferChain(self); // buf2->next = buf1; self->writerChain = buf1; self->meta_buf = mbuf_create(); /* Initialize mutex and condition variable objects */ pthread_cond_init(&self->semaphore, NULL); pthread_mutex_init(&self->lock, NULL); /* 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, threadStart, (void*)self); return (BufferedWriterHdl)self; }
int thpool_add_thread(void* pri_arg) { thread_data* th_data = (thread_data*)malloc(sizeof(thread_data)); th_data->tid = th_id++; th_data->pbuf = mbuf_create(TH_QUEUE_BUF_SIZE); th_data->parg = pri_arg; cond_init(&th_data->cond); pthread_t t; int rc = pthread_create(&t, 0, base_work, th_data); if( 0 != rc ) { fprintf(stderr, "thpool: create thread error\n"); mbuf_delete(th_data->pbuf); free(th_data); return -1; } hash_set_int(g_th_pool, th_data->tid, th_data); pth_pool[curr_num++] = th_data; return th_data->tid; }
struct mbuf *mbuf_get(struct context *ctx) { struct mbuf *mbuf; uint8_t *buf; mbuf = mbuf_create(ctx); if (mbuf == NULL) { return NULL; } buf = (uint8_t *)mbuf - ctx->mbuf_offset; mbuf->start = buf; mbuf->end = buf + ctx->mbuf_offset; mbuf->pos = mbuf->start; mbuf->last = mbuf->start; mbuf->queue = NULL; mbuf->refcount = 0; TAILQ_NEXT(mbuf, next) = NULL; ctx->mstats.buffers++; return mbuf; }
static bytea * decrypt_internal(int is_pubenc, int need_text, text *data, text *key, text *keypsw, text *args) { int err; MBuf *src = NULL, *dst = NULL; uint8 tmp[VARHDRSZ]; uint8 *restmp; bytea *res; int res_len; PGP_Context *ctx = NULL; struct debug_expect ex; int got_unicode = 0; init_work(&ctx, need_text, args, &ex); src = mbuf_create_from_data((uint8 *) VARDATA(data), VARSIZE(data) - VARHDRSZ); dst = mbuf_create(VARSIZE(data) + 2048); /* * reserve room for header */ mbuf_append(dst, tmp, VARHDRSZ); /* * set key */ if (is_pubenc) { uint8 *psw = NULL; int psw_len = 0; MBuf *kbuf; if (keypsw) { psw = (uint8 *) VARDATA(keypsw); psw_len = VARSIZE(keypsw) - VARHDRSZ; } kbuf = create_mbuf_from_vardata(key); err = pgp_set_pubkey(ctx, kbuf, psw, psw_len, 1); mbuf_free(kbuf); } else err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key), VARSIZE(key) - VARHDRSZ); /* * decrypt */ if (err >= 0) err = pgp_decrypt(ctx, src, dst); /* * failed? */ if (err < 0) goto out; if (ex.expect) check_expect(ctx, &ex); /* remember the setting */ got_unicode = pgp_get_unicode_mode(ctx); out: if (src) mbuf_free(src); if (ctx) pgp_free(ctx); if (err) { px_set_debug_handler(NULL); if (dst) mbuf_free(dst); ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), errmsg("%s", px_strerror(err)))); } res_len = mbuf_steal_data(dst, &restmp); mbuf_free(dst); /* res_len includes VARHDRSZ */ res = (bytea *) restmp; SET_VARSIZE(res, res_len); if (need_text && got_unicode) { text *utf = convert_from_utf8(res); if (utf != res) { clear_and_pfree(res); res = utf; } } px_set_debug_handler(NULL); /* * add successfull decryptions also into RNG */ add_entropy(res, key, keypsw); return res; }
static bytea * encrypt_internal(int is_pubenc, int is_text, text *data, text *key, text *args) { MBuf *src, *dst; uint8 tmp[VARHDRSZ]; uint8 *restmp; bytea *res; int res_len; PGP_Context *ctx; int err; struct debug_expect ex; text *tmp_data = NULL; /* * Add data and key info RNG. */ add_entropy(data, key, NULL); init_work(&ctx, is_text, args, &ex); if (is_text && pgp_get_unicode_mode(ctx)) { tmp_data = convert_to_utf8(data); if (tmp_data == data) tmp_data = NULL; else data = tmp_data; } src = create_mbuf_from_vardata(data); dst = mbuf_create(VARSIZE(data) + 128); /* * reserve room for header */ mbuf_append(dst, tmp, VARHDRSZ); /* * set key */ if (is_pubenc) { MBuf *kbuf = create_mbuf_from_vardata(key); err = pgp_set_pubkey(ctx, kbuf, NULL, 0, 0); mbuf_free(kbuf); } else err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key), VARSIZE(key) - VARHDRSZ); /* * encrypt */ if (err >= 0) err = pgp_encrypt(ctx, src, dst); /* * check for error */ if (err) { if (ex.debug) px_set_debug_handler(NULL); if (tmp_data) clear_and_pfree(tmp_data); pgp_free(ctx); mbuf_free(src); mbuf_free(dst); ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), errmsg("%s", px_strerror(err)))); } /* res_len includes VARHDRSZ */ res_len = mbuf_steal_data(dst, &restmp); res = (bytea *) restmp; SET_VARSIZE(res, res_len); if (tmp_data) clear_and_pfree(tmp_data); pgp_free(ctx); mbuf_free(src); mbuf_free(dst); px_set_debug_handler(NULL); return res; }