FS-10165: Removed dependancy and autoconf check for libsodium from libks. Moved DHT, bencode, and related tests into libblade. Still requires refactoring in blade from ks_* to blade_*.

This commit is contained in:
Shane Bryldt committed 2017-03-22 17:47:33 -05:00
1 parent 716f02897a
commit 5cff01b2a8
28 files changed
+48 -59

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+60
View File
@@ -0,0 +1,60 @@
#include "ks_dht.h"
#include "ks_dht-int.h"
#include "sodium.h"
KS_DECLARE(ks_status_t) ks_dht_datagram_create(ks_dht_datagram_t **datagram,
ks_pool_t *pool,
ks_dht_t *dht,
ks_dht_endpoint_t *endpoint,
const ks_sockaddr_t *raddr)
{
ks_dht_datagram_t *dg;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(datagram);
ks_assert(pool);
ks_assert(dht);
ks_assert(endpoint);
ks_assert(raddr);
ks_assert(raddr->family == AF_INET || raddr->family == AF_INET6);
*datagram = dg = ks_pool_alloc(pool, sizeof(ks_dht_datagram_t));
ks_assert(dg);
dg->pool = pool;
dg->dht = dht;
dg->endpoint = endpoint;
dg->raddr = *raddr;
memcpy(dg->buffer, dht->recv_buffer, dht->recv_buffer_length);
dg->buffer_length = dht->recv_buffer_length;
// done:
if (ret != KS_STATUS_SUCCESS) {
ks_dht_datagram_destroy(datagram);
}
return ret;
}
KS_DECLARE(void) ks_dht_datagram_destroy(ks_dht_datagram_t **datagram)
{
ks_dht_datagram_t *dg;
ks_assert(datagram);
ks_assert(*datagram);
dg = *datagram;
ks_pool_free(dg->pool, datagram);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
+65
View File
@@ -0,0 +1,65 @@
#include "ks_dht.h"
#include "ks_dht-int.h"
#include "sodium.h"
KS_DECLARE(ks_status_t) ks_dht_distribute_create(ks_dht_distribute_t **distribute,
ks_pool_t *pool,
ks_dht_storageitem_callback_t callback,
void *data,
int64_t cas,
ks_dht_storageitem_t *item)
{
ks_dht_distribute_t *d;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(distribute);
ks_assert(pool);
ks_assert(cas >= 0);
ks_assert(item);
*distribute = d = ks_pool_alloc(pool, sizeof(ks_dht_distribute_t));
ks_assert(d);
d->pool = pool;
d->callback = callback;
d->data = data;
ks_mutex_create(&d->mutex, KS_MUTEX_FLAG_DEFAULT, d->pool);
ks_assert(d->mutex);
d->cas = cas;
d->item = item;
ks_dht_storageitem_reference(d->item);
// done:
if (ret != KS_STATUS_SUCCESS) {
if (d) ks_dht_distribute_destroy(distribute);
}
return ret;
}
KS_DECLARE(void) ks_dht_distribute_destroy(ks_dht_distribute_t **distribute)
{
ks_dht_distribute_t *d;
ks_assert(distribute);
ks_assert(*distribute);
d = *distribute;
if (d->mutex) ks_mutex_destroy(&d->mutex);
ks_dht_storageitem_dereference(d->item);
ks_pool_free(d->pool, distribute);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
+61
View File
@@ -0,0 +1,61 @@
#include "ks_dht.h"
#include "ks_dht-int.h"
#include "sodium.h"
/**
*
*/
KS_DECLARE(ks_status_t) ks_dht_endpoint_create(ks_dht_endpoint_t **endpoint,
ks_pool_t *pool,
const ks_sockaddr_t *addr,
ks_socket_t sock)
{
ks_dht_endpoint_t *ep;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(endpoint);
ks_assert(pool);
ks_assert(addr);
ks_assert(addr->family == AF_INET || addr->family == AF_INET6);
*endpoint = ep = ks_pool_alloc(pool, sizeof(ks_dht_endpoint_t));
ks_assert(ep);
ep->pool = pool;
ep->addr = *addr;
ep->sock = sock;
// done:
if (ret != KS_STATUS_SUCCESS) {
if (ep) ks_dht_endpoint_destroy(endpoint);
}
return ret;
}
/**
*
*/
KS_DECLARE(void) ks_dht_endpoint_destroy(ks_dht_endpoint_t **endpoint)
{
ks_dht_endpoint_t *ep;
ks_assert(endpoint);
ks_assert(*endpoint);
ep = *endpoint;
if (ep->sock != KS_SOCK_INVALID) ks_socket_close(&ep->sock);
ks_pool_free(ep->pool, endpoint);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
+136
View File
@@ -0,0 +1,136 @@
#include "ks_dht.h"
#include "ks_dht-int.h"
KS_DECLARE(ks_status_t) ks_dht_job_create(ks_dht_job_t **job,
ks_pool_t *pool,
const ks_sockaddr_t *raddr,
int32_t attempts,
void *data)
{
ks_dht_job_t *j;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(job);
ks_assert(pool);
//ks_assert(dht);
ks_assert(attempts > 0 && attempts <= 10);
*job = j = ks_pool_alloc(pool, sizeof(ks_dht_job_t));
ks_assert(j);
j->pool = pool;
j->state = KS_DHT_JOB_STATE_QUERYING;
if (raddr) j->raddr = *raddr;
j->attempts = attempts;
j->data = data;
// done:
if (ret != KS_STATUS_SUCCESS) {
if (j) ks_dht_job_destroy(job);
}
return ret;
}
KS_DECLARE(void) ks_dht_job_build_ping(ks_dht_job_t *job, ks_dht_job_callback_t query_callback, ks_dht_job_callback_t finish_callback)
{
ks_assert(job);
ks_assert(query_callback);
job->query_callback = query_callback;
job->finish_callback = finish_callback;
}
KS_DECLARE(void) ks_dht_job_build_findnode(ks_dht_job_t *job,
ks_dht_job_callback_t query_callback,
ks_dht_job_callback_t finish_callback,
ks_dht_nodeid_t *target)
{
ks_assert(job);
ks_assert(query_callback);
ks_assert(target);
job->query_callback = query_callback;
job->finish_callback = finish_callback;
job->query_target = *target;
}
KS_DECLARE(void) ks_dht_job_build_get(ks_dht_job_t *job,
ks_dht_job_callback_t query_callback,
ks_dht_job_callback_t finish_callback,
ks_dht_nodeid_t *target,
const uint8_t *salt,
ks_size_t salt_length)
{
ks_assert(job);
ks_assert(query_callback);
ks_assert(target);
job->query_callback = query_callback;
job->finish_callback = finish_callback;
job->query_target = *target;
if (salt && salt_length > 0) job->query_salt = ben_blob(salt, salt_length);
}
KS_DECLARE(void) ks_dht_job_build_put(ks_dht_job_t *job,
ks_dht_job_callback_t query_callback,
ks_dht_job_callback_t finish_callback,
ks_dht_token_t *token,
int64_t cas,
ks_dht_storageitem_t *item)
{
ks_assert(job);
ks_assert(query_callback);
ks_assert(token);
ks_assert(item);
job->query_callback = query_callback;
job->finish_callback = finish_callback;
job->query_token = *token;
job->query_cas = cas;
job->query_storageitem = item;
ks_dht_storageitem_reference(job->query_storageitem);
}
KS_DECLARE(void) ks_dht_job_build_search(ks_dht_job_t *job,
ks_dht_job_callback_t query_callback,
ks_dht_job_callback_t finish_callback)
{
ks_assert(job);
ks_assert(query_callback);
job->query_callback = query_callback;
job->finish_callback = finish_callback;
}
KS_DECLARE(void) ks_dht_job_destroy(ks_dht_job_t **job)
{
ks_dht_job_t *j;
ks_assert(job);
ks_assert(*job);
j = *job;
if (j->query_salt) ben_free(j->query_salt);
if (j->response_id) ks_dhtrt_release_node(j->response_id);
for (int32_t i = 0; i < j->response_nodes_count; ++i) ks_dhtrt_release_node(j->response_nodes[i]);
for (int32_t i = 0; i < j->response_nodes6_count; ++i) ks_dhtrt_release_node(j->response_nodes6[i]);
if (j->query_storageitem) ks_dht_storageitem_dereference(j->query_storageitem);
if (j->response_storageitem) ks_dht_storageitem_dereference(j->response_storageitem);
if (j->error_description) ben_free(j->error_description);
ks_pool_free(j->pool, job);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
+122
View File
@@ -0,0 +1,122 @@
#include "ks_dht.h"
#include "ks_dht-int.h"
KS_DECLARE(ks_status_t) ks_dht_message_create(ks_dht_message_t **message,
ks_pool_t *pool,
ks_dht_endpoint_t *endpoint,
const ks_sockaddr_t *raddr,
ks_bool_t alloc_data)
{
ks_dht_message_t *m;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(message);
ks_assert(pool);
*message = m = ks_pool_alloc(pool, sizeof(ks_dht_message_t));
ks_assert(m);
m->pool = pool;
m->endpoint = endpoint;
m->raddr = *raddr;
if (alloc_data) {
m->data = ben_dict();
ks_assert(m->data);
}
// done:
if (ret != KS_STATUS_SUCCESS) {
ks_dht_message_destroy(message);
}
return ret;
}
KS_DECLARE(void) ks_dht_message_destroy(ks_dht_message_t **message)
{
ks_dht_message_t *m;
ks_assert(message);
ks_assert(*message);
m = *message;
if (m->data) {
ben_free(m->data);
m->data = NULL;
}
ks_pool_free(m->pool, message);
}
KS_DECLARE(ks_status_t) ks_dht_message_parse(ks_dht_message_t *message, const uint8_t *buffer, ks_size_t buffer_length)
{
struct bencode *t;
struct bencode *y;
const char *tv;
const char *yv;
ks_size_t tv_len;
ks_size_t yv_len;
ks_assert(message);
ks_assert(message->pool);
ks_assert(buffer);
ks_assert(!message->data);
message->data = ben_decode((const void *)buffer, buffer_length);
if (!message->data) {
ks_log(KS_LOG_DEBUG, "Message cannot be decoded\n");
return KS_STATUS_FAIL;
}
ks_log(KS_LOG_DEBUG, "Message decoded\n");
ks_log(KS_LOG_DEBUG, "%s\n", ben_print(message->data));
t = ben_dict_get_by_str(message->data, "t");
if (!t) {
ks_log(KS_LOG_DEBUG, "Message missing required key 't'\n");
return KS_STATUS_FAIL;
}
tv = ben_str_val(t);
tv_len = ben_str_len(t);
if (tv_len > KS_DHT_MESSAGE_TRANSACTIONID_MAX_SIZE) {
ks_log(KS_LOG_DEBUG, "Message 't' value has an unexpectedly large size of %d\n", tv_len);
return KS_STATUS_FAIL;
}
memcpy(message->transactionid, tv, tv_len);
message->transactionid_length = tv_len;
// @todo hex output of transactionid
//ks_log(KS_LOG_DEBUG, "Message transaction id is %d\n", message->transactionid);
y = ben_dict_get_by_str(message->data, "y");
if (!y) {
ks_log(KS_LOG_DEBUG, "Message missing required key 'y'\n");
return KS_STATUS_FAIL;
}
yv = ben_str_val(y);
yv_len = ben_str_len(y);
if (yv_len >= KS_DHT_MESSAGE_TYPE_MAX_SIZE) {
ks_log(KS_LOG_DEBUG, "Message 'y' value has an unexpectedly large size of %d\n", yv_len);
return KS_STATUS_FAIL;
}
memcpy(message->type, yv, yv_len);
message->type[yv_len] = '\0';
//ks_log(KS_LOG_DEBUG, "Message type is '%s'\n", message->type);
return KS_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
+62
View File
@@ -0,0 +1,62 @@
#include "ks_dht.h"
#include "ks_dht-int.h"
#include "sodium.h"
KS_DECLARE(ks_status_t) ks_dht_publish_create(ks_dht_publish_t **publish,
ks_pool_t *pool,
ks_dht_job_callback_t callback,
void *data,
int64_t cas,
ks_dht_storageitem_t *item)
{
ks_dht_publish_t *p;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(publish);
ks_assert(pool);
ks_assert(cas >= 0);
ks_assert(item);
*publish = p = ks_pool_alloc(pool, sizeof(ks_dht_publish_t));
ks_assert(p);
p->pool = pool;
p->callback = callback;
p->data = data;
p->cas = cas;
p->item = item;
ks_dht_storageitem_reference(p->item);
// done:
if (ret != KS_STATUS_SUCCESS) {
if (p) ks_dht_publish_destroy(publish);
}
return ret;
}
KS_DECLARE(void) ks_dht_publish_destroy(ks_dht_publish_t **publish)
{
ks_dht_publish_t *p;
ks_assert(publish);
ks_assert(*publish);
p = *publish;
ks_dht_storageitem_dereference(p->item);
ks_pool_free(p->pool, publish);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
+71
View File
@@ -0,0 +1,71 @@
#include "ks_dht.h"
#include "ks_dht-int.h"
#include "sodium.h"
KS_DECLARE(ks_status_t) ks_dht_search_create(ks_dht_search_t **search,
ks_pool_t *pool,
ks_dhtrt_routetable_t *table,
const ks_dht_nodeid_t *target,
ks_dht_job_callback_t callback,
void *data)
{
ks_dht_search_t *s;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(search);
ks_assert(pool);
ks_assert(table);
ks_assert(target);
*search = s = ks_pool_alloc(pool, sizeof(ks_dht_search_t));
ks_assert(s);
s->pool = pool;
ks_mutex_create(&s->mutex, KS_MUTEX_FLAG_DEFAULT, s->pool);
ks_assert(s->mutex);
s->table = table;
memcpy(s->target.id, target->id, KS_DHT_NODEID_SIZE);
s->callback = callback;
s->data = data;
ks_hash_create(&s->searched, KS_HASH_MODE_ARBITRARY, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, s->pool);
ks_assert(s->searched);
ks_hash_set_keysize(s->searched, KS_DHT_NODEID_SIZE);
s->searching = 0;
// done:
if (ret != KS_STATUS_SUCCESS) {
if (s) ks_dht_search_destroy(search);
}
return ret;
}
KS_DECLARE(void) ks_dht_search_destroy(ks_dht_search_t **search)
{
ks_dht_search_t *s;
ks_assert(search);
ks_assert(*search);
s = *search;
if (s->searched) ks_hash_destroy(&s->searched);
if (s->mutex) ks_mutex_destroy(&s->mutex);
ks_pool_free(s->pool, search);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
+214
View File
@@ -0,0 +1,214 @@
#include "ks_dht.h"
#include "ks_dht-int.h"
#include "sodium.h"
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_immutable_internal(ks_dht_storageitem_t **item,
ks_pool_t *pool,
ks_dht_nodeid_t *target,
struct bencode *v,
ks_bool_t clone_v)
{
ks_dht_storageitem_t *si;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(item);
ks_assert(pool);
ks_assert(v);
ks_assert(SHA_DIGEST_LENGTH == KS_DHT_NODEID_SIZE);
*item = si = ks_pool_alloc(pool, sizeof(ks_dht_storageitem_t));
ks_assert(si);
si->pool = pool;
si->id = *target;
si->mutable = KS_FALSE;
si->expiration = ks_time_now() + ((ks_time_t)KS_DHT_STORAGEITEM_EXPIRATION * KS_USEC_PER_SEC);
si->keepalive = ks_time_now() + ((ks_time_t)KS_DHT_STORAGEITEM_KEEPALIVE * KS_USEC_PER_SEC);
si->v = clone_v ? ben_clone(v) : v;
ks_assert(si->v);
si->refc = 1;
// done:
if (ret != KS_STATUS_SUCCESS) {
if (si) ks_dht_storageitem_destroy(item);
}
return ret;
}
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_immutable(ks_dht_storageitem_t **item,
ks_pool_t *pool,
ks_dht_nodeid_t *target,
const uint8_t *value,
ks_size_t value_length)
{
struct bencode *v = NULL;
ks_assert(item);
ks_assert(pool);
ks_assert(value);
ks_assert(value_length > 0);
ks_assert(SHA_DIGEST_LENGTH == KS_DHT_NODEID_SIZE);
v = ben_blob(value, value_length);
ks_assert(v);
return ks_dht_storageitem_create_immutable_internal(item, pool, target, v, KS_FALSE);
}
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_mutable_internal(ks_dht_storageitem_t **item,
ks_pool_t *pool,
ks_dht_nodeid_t *target,
struct bencode *v,
ks_bool_t clone_v,
ks_dht_storageitem_pkey_t *pk,
struct bencode *salt,
ks_bool_t clone_salt,
int64_t sequence,
ks_dht_storageitem_signature_t *signature)
{
ks_dht_storageitem_t *si;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(item);
ks_assert(pool);
ks_assert(v);
ks_assert(SHA_DIGEST_LENGTH == KS_DHT_NODEID_SIZE);
ks_assert(pk);
ks_assert(signature);
*item = si = ks_pool_alloc(pool, sizeof(ks_dht_storageitem_t));
ks_assert(si);
si->pool = pool;
si->id = *target;
si->mutable = KS_TRUE;
si->expiration = ks_time_now() + ((ks_time_t)KS_DHT_STORAGEITEM_EXPIRATION * KS_USEC_PER_SEC);
si->keepalive = ks_time_now() + ((ks_time_t)KS_DHT_STORAGEITEM_KEEPALIVE * KS_USEC_PER_SEC);
si->v = clone_v ? ben_clone(v) : v;
ks_assert(si->v);
si->refc = 1;
ks_mutex_create(&si->mutex, KS_MUTEX_FLAG_DEFAULT, si->pool);
ks_assert(si->mutex);
si->pk = *pk;
if (salt) {
si->salt = clone_salt ? ben_clone(salt) : salt;
ks_assert(si->salt);
}
si->seq = sequence;
si->sig = *signature;
// done:
if (ret != KS_STATUS_SUCCESS) {
if (si) ks_dht_storageitem_destroy(item);
}
return ret;
}
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_mutable(ks_dht_storageitem_t **item,
ks_pool_t *pool,
ks_dht_nodeid_t *target,
const uint8_t *value,
ks_size_t value_length,
ks_dht_storageitem_pkey_t *pk,
const uint8_t *salt,
ks_size_t salt_length,
int64_t sequence,
ks_dht_storageitem_signature_t *signature)
{
struct bencode *v = NULL;
struct bencode *s = NULL;
ks_assert(item);
ks_assert(pool);
ks_assert(value);
ks_assert(value_length > 0);
ks_assert(SHA_DIGEST_LENGTH == KS_DHT_NODEID_SIZE);
ks_assert(pk);
ks_assert(signature);
v = ben_blob(value, value_length);
if (salt && salt_length > 0) s = ben_blob(salt, salt_length);
return ks_dht_storageitem_create_mutable_internal(item, pool, target, v, KS_FALSE, pk, s, KS_FALSE, sequence, signature);
}
KS_DECLARE(void) ks_dht_storageitem_update_mutable(ks_dht_storageitem_t *item, struct bencode *v, int64_t sequence, ks_dht_storageitem_signature_t *signature)
{
ks_assert(item);
ks_assert(v);
ks_assert(sequence);
ks_assert(signature);
ks_mutex_lock(item->mutex);
ben_free(item->v);
item->v = ben_clone(v);
item->seq = sequence;
item->sig = *signature;
ks_mutex_unlock(item->mutex);
}
/**
*
*/
KS_DECLARE(void) ks_dht_storageitem_destroy(ks_dht_storageitem_t **item)
{
ks_dht_storageitem_t *si;
ks_assert(item);
ks_assert(*item);
si = *item;
if (si->v) {
ben_free(si->v);
si->v = NULL;
}
if (si->mutex) ks_mutex_destroy(&si->mutex);
if (si->salt) {
ben_free(si->salt);
si->salt = NULL;
}
ks_pool_free(si->pool, item);
}
KS_DECLARE(void) ks_dht_storageitem_reference(ks_dht_storageitem_t *item)
{
ks_assert(item);
ks_mutex_lock(item->mutex);
item->refc++;
ks_mutex_unlock(item->mutex);
}
KS_DECLARE(void) ks_dht_storageitem_dereference(ks_dht_storageitem_t *item)
{
ks_assert(item);
ks_mutex_lock(item->mutex);
item->refc--;
ks_mutex_unlock(item->mutex);
ks_assert(item->refc >= 0);
}
KS_DECLARE(void) ks_dht_storageitem_callback(ks_dht_storageitem_t *item, ks_dht_storageitem_callback_t callback)
{
ks_assert(item);
item->callback = callback;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
@@ -0,0 +1,54 @@
#include "ks_dht.h"
#include "ks_dht-int.h"
KS_DECLARE(ks_status_t) ks_dht_transaction_create(ks_dht_transaction_t **transaction,
ks_pool_t *pool,
ks_dht_job_t *job,
uint32_t transactionid,
ks_dht_job_callback_t callback)
{
ks_dht_transaction_t *t;
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(transaction);
ks_assert(pool);
ks_assert(job);
*transaction = t = ks_pool_alloc(pool, sizeof(ks_dht_transaction_t));
ks_assert(t);
t->pool = pool;
t->job = job;
t->transactionid = transactionid;
t->callback = callback;
t->expiration = ks_time_now() + ((ks_time_t)KS_DHT_TRANSACTION_EXPIRATION * KS_USEC_PER_SEC);
// done:
if (ret != KS_STATUS_SUCCESS) {
if (t) ks_dht_transaction_destroy(transaction);
}
return ret;
}
KS_DECLARE(void) ks_dht_transaction_destroy(ks_dht_transaction_t **transaction)
{
ks_dht_transaction_t *t;
ks_assert(transaction);
ks_assert(*transaction);
t = *transaction;
ks_pool_free(t->pool, transaction);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/