Triton-commits
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
January 2015
- 2 participants
- 33 discussions
branch, trac-323-sos, updated. 3ac529bca05c82b61ce25a43d03a5f94ae7915bd
by noreply@mcs.anl.gov 30 Jan '15
by noreply@mcs.anl.gov 30 Jan '15
30 Jan '15
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, trac-323-sos has been updated
via 3ac529bca05c82b61ce25a43d03a5f94ae7915bd (commit)
via 21251921ac9722ed88f3d334bc569d3c23a4d946 (commit)
via 32782d77e1ce4373f723e14fc687dde7f4f9a62e (commit)
via 443dea95c85b62c4b3d4a8a6a20e529c9c4dac1a (commit)
from 3773521d77cfd3ce0c85e949dc33bc32f9947f9d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 3ac529bca05c82b61ce25a43d03a5f94ae7915bd
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Fri Jan 30 11:46:48 2015 -0600
infrastructure to pass client placement calcs to servers
necessary to correctly do striped allocation
commit 21251921ac9722ed88f3d334bc569d3c23a4d946
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Thu Jan 29 14:50:13 2015 -0600
add option to mkdat to echo generated objects to stdout
commit 32782d77e1ce4373f723e14fc687dde7f4f9a62e
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Thu Jan 29 14:32:13 2015 -0600
striped allocation option to mkdat
commit 443dea95c85b62c4b3d4a8a6a20e529c9c4dac1a
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Thu Jan 29 13:17:53 2015 -0600
refactor object creation code in mkdat
(will be adding more later, specifically for striped IO)
-----------------------------------------------------------------------
Summary of changes:
code/src/admin-tools/triton-mkdat.ae | 322 ++++++++++++++++++-------
code/src/admin-tools/triton-show-placement.ae | 2 +-
code/src/asg/asg-internal.ae | 82 ++++---
code/src/placement/Makefile.subdir | 3 +-
code/src/placement/placement-1d.c | 18 +-
code/src/placement/placement-common.c | 46 ----
code/src/placement/placement-common.h | 27 --
code/src/placement/placement-method.c | 117 +++++++++
code/src/placement/placement-method.h | 48 ++++-
code/src/placement/placement-multiring.c | 91 ++++++-
code/src/placement/placement.ae | 21 +-
code/src/placement/placement.h | 44 +++-
code/src/replicated-osd/rosd-alloc.ae | 8 +-
code/src/replicated-osd/rosd.ae | 2 +-
code/src/replicated-osd/rosd.hae | 2 +
15 files changed, 598 insertions(+), 235 deletions(-)
delete mode 100644 code/src/placement/placement-common.c
delete mode 100644 code/src/placement/placement-common.h
create mode 100644 code/src/placement/placement-method.c
Diff of changes:
diff --git a/code/src/admin-tools/triton-mkdat.ae b/code/src/admin-tools/triton-mkdat.ae
index d889d7d..1ac64a8 100644
--- a/code/src/admin-tools/triton-mkdat.ae
+++ b/code/src/admin-tools/triton-mkdat.ae
@@ -21,6 +21,7 @@ static const char * usage_str =
" Create dummy data given OPTIONS, using SERVER as the contact point\n"
"Options:\n"
" -h, --help - print this message and exit\n"
+" -e, --echo - print all created objects to standard out in integer format\n"
" -o, --num-objects N - create N objects\n"
" (default - N=1)\n"
" -r, --replication-factor R - use a replication factor of R for each object\n"
@@ -39,8 +40,13 @@ static const char * usage_str =
" -d, --object-dist DIST - distribution of object IDs.\n"
" DIST expected to be one of \"seq\", <TODO: more dists>\n"
" seq - OIDs assigned in increasing order (e.g., 1, 2, 3, ...)\n"
-" alloc - OIDs assigned using the rosd-alloc RPC (one by one,\n"
-" rather than batched). The request is sent to SERVER\n"
+" alloc - OIDs created using the rosd-alloc RPC (one by one,\n"
+" rather than batched). Servers to contact are randomly chosen.\n"
+" striped-alloc - OIDs creating using the rosd-alloc RPC (one by one,\n"
+" rather than batched). Servers to contact are chosen in such\n"
+" a way that no objects+replicas fall upon the same server.\n"
+" The program will fail if it is unable to satisfy the request\n"
+" for the given object/replica count.\n"
" (default - seq)\n"
" -t, --time - time write phase of program, printing to stdout\n"
" NOTE: timing is performed at object-granularity\n"
@@ -59,10 +65,12 @@ static const char * usage_str =
enum object_dist {
SEQ,
- ALLOC,
+ ALLOC_RANDOM,
+ ALLOC_STRIPED
};
struct opt_vals{
+ int echo;
int64_t num_objects;
uint32_t replication_factor;
int64_t num_forks;
@@ -77,6 +85,7 @@ struct opt_vals{
static const struct option long_opts[] = {
{"help", no_argument, 0, 0},
+ {"echo", no_argument, 0, 0},
{"num-objects", required_argument, 0, 0},
{"replication-factor", required_argument, 0, 0},
{"num-forks", required_argument, 0, 0},
@@ -92,6 +101,7 @@ static const struct option long_opts[] = {
/* options, filled with defaults */
static struct opt_vals opts = {
+ 0,
1,
1,
1,
@@ -114,6 +124,194 @@ static double tsToS(struct timespec ts){
return (double) ts.tv_sec + 1e-9 * ts.tv_nsec;
}
+static char * oid_string(uint64_t obj){
+ return triton_uint128_to_string(triton_uint128_from_uint64(obj));
+}
+
+static __blocking uint64_t * create_seq_objects(
+ int64_t num_objects,
+ uint32_t replication_factor) {
+ int64_t i;
+ triton_ret_t tret;
+ uint64_t * ret;
+
+ ret = malloc(num_objects * sizeof(*ret));
+ assert(ret != NULL);
+
+ for (i = 1; i <= num_objects; i++) {
+ tret = remote_triton_rpc_rosd_create(0, i,
+ replication_factor, 0);
+ if (triton_error_equal(tret, TRITON_ERR_EXIST)) {
+ fprintf(stderr, "Objects %s exists, need to delete manually for "
+ "the time being\n", oid_string(i));
+ triton_error_destroy(tret);
+ free(ret);
+ return NULL;
+ }
+ else if (triton_is_error(tret)) {
+ triton_error_print(tret, "triton-mkdat: "
+ "failed to create object %s", oid_string(i));
+ free(ret);
+ return NULL;
+ }
+ else
+ ret[i-1] = i;
+ }
+ return ret;
+}
+
+static __blocking uint64_t * alloc_objects(
+ int64_t num_objects,
+ uint32_t replication_factor) {
+ triton_random_t *rng;
+ uint64_t rand_id;
+ triton_node_t *nodelist;
+ int nnodes;
+ char *rand_serv_str;
+ na_addr_t rand_serv_addr;
+ int rand_serv_idx;
+ triton_ret_t tret;
+ int64_t i;
+ uint64_t *ret;
+
+ tret = triton_random_create(&rng, 0, NULL, 0);
+ assert(!triton_is_error(tret));
+
+ tret = system_state_list_nodes("addr", &nodelist, &nnodes);
+ if (triton_is_error(tret)) {
+ triton_error_print(tret, "unable to get triton nodelist");
+ return NULL;
+ }
+
+ ret = malloc(num_objects * sizeof(*ret));
+ assert(ret != NULL);
+
+ /* TODO: aesop-ize */
+ tret = TRITON_SUCCESS;
+ for (i = 0; i < num_objects && tret == TRITON_SUCCESS; i++) {
+ tret = triton_random64(rng, &rand_id);
+ rand_serv_idx = rand_id % nnodes;
+ if (!triton_is_error(tret)) {
+ rand_serv_str = system_state_get(nodelist[rand_serv_idx],
+ "addr");
+ if (rand_serv_str != NULL) {
+ tret = triton_mercury_addr_lookup(rand_serv_str,
+ &rand_serv_addr);
+ if (!triton_is_error(tret))
+ tret = remote_triton_rpc_rosd_alloc(rand_serv_addr, 0,
+ 1, opts.replication_factor, 0, NULL, &ret[i]);
+ free(rand_serv_str);
+ }
+ else
+ tret = TRITON_ERR_UNKNOWN;
+ }
+ }
+
+ free(nodelist);
+ triton_random_destroy(rng);
+
+ if (triton_is_error(tret)) {
+ triton_error_print(tret, "triton-mkdat: failed to alloc object");
+ triton_error_destroy(tret);
+ free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+static __blocking uint64_t * alloc_striped_objects(
+ int64_t num_objects,
+ uint32_t replication_factor) {
+
+ triton_random_t *rng;
+ triton_node_t *nodelist;
+ int nnodes;
+ triton_ret_t tret;
+ int rc;
+ uint64_t *ret;
+ triton_place_ctx ctx;
+
+ tret = triton_random_create(&rng, 0, NULL, 0);
+ assert(!triton_is_error(tret));
+
+ tret = system_state_list_nodes("addr", &nodelist, &nnodes);
+ if (triton_is_error(tret)) {
+ triton_error_print(tret, "unable to get triton nodelist");
+ return NULL;
+ }
+
+ ret = malloc(num_objects * sizeof(*ret));
+ assert(ret != NULL);
+
+ ctx = triton_place_make_ctx();
+ assert(ctx != NULL);
+
+ tret = triton_place_gen_random_unique_set(rng, (int) num_objects,
+ (int) replication_factor, nodelist, ctx);
+ if (triton_is_error(tret)) {
+ triton_error_print(tret,
+ "unable to allocate %ld objects (%u replicas) "
+ "to unique servers", num_objects, replication_factor);
+ free(ret);
+ return NULL;
+ }
+
+ /* now request the objects individually (these are guaranteed to be on
+ * different servers) */
+ triton_ret_t pwait_ret = TRITON_SUCCESS;
+ pwait {
+ pprivate int64_t i;
+ pprivate na_addr_t addr;
+ pprivate char * server_str;
+ pprivate triton_ret_t b_tret;
+ for (i = 0; i < num_objects; i++) {
+ pbranch {
+ server_str = system_state_get(nodelist[i], "addr");
+ if (server_str != NULL) {
+ b_tret = triton_mercury_addr_lookup(server_str, &addr);
+ if (!triton_is_error(b_tret))
+ b_tret = remote_triton_rpc_rosd_alloc(addr, 0, 1,
+ replication_factor, 0, ctx, &ret[i]);
+ }
+ else
+ b_tret = TRITON_ERR_UNKNOWN;
+ if (triton_is_error(b_tret)) {
+ triton_error_print(b_tret, "error allocating object");
+ pwait_ret = triton_error_dup(b_tret);
+ }
+ free(server_str);
+ }
+ }
+ }
+ if (triton_is_error(pwait_ret)) {
+ free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+static __blocking uint64_t * create_objects(
+ int64_t num_objects,
+ uint32_t replication_factor,
+ enum object_dist dist){
+ uint64_t *ret;
+ switch(dist) {
+ case SEQ:
+ ret = create_seq_objects(num_objects, replication_factor);
+ break;
+ case ALLOC_RANDOM:
+ ret = alloc_objects(num_objects, replication_factor);
+ break;
+ case ALLOC_STRIPED:
+ ret = alloc_striped_objects(num_objects, replication_factor);
+ break;
+ default:
+ assert(0);
+ }
+ return ret;
+}
+
__blocking int aesop_main(int argc, char **argv){
triton_ret_t tret;
@@ -155,24 +353,9 @@ __blocking int aesop_main(int argc, char **argv){
return(-1);
}
- /* for randomly selecting servers to write to (used */
- triton_random_t *rng;
- uint64_t rand_id;
- triton_node_t *nodelist;
- int nnodes;
- char *rand_serv_str;
- na_addr_t rand_serv_addr;
- int rand_serv_idx;
-
- tret = triton_random_create(&rng, 0, NULL, 0);
- assert(!triton_is_error(tret));
- tret = system_state_list_nodes("addr", &nodelist, &nnodes);
- assert(!triton_is_error(tret));
-
/* allocate a buffer large enough to hold all data in a single write */
unsigned char * buffer;
-
buffer = malloc(opts.size_per_write);
if (buffer == NULL) {
fprintf(stderr, "unable to allocate buffer of size %lu\n",
@@ -197,69 +380,29 @@ __blocking int aesop_main(int argc, char **argv){
assert((times = malloc(sizeof(double) * opts.num_objects)));
}
+ /* perform the object allocation/creation up front */
+ uint64_t *oids;
+ oids = create_objects(opts.num_objects, opts.replication_factor, opts.dist);
+ if (oids == NULL) {
+ triton_mercury_engine_finalize();
+ return 1;
+ }
+
/* perform the writes */
int64_t obj, fork, write_nr;
uint64_t oid;
uint128_t oid_l;
- for (obj = 1; obj <= opts.num_objects; obj++){
+ for (obj = 0; obj < opts.num_objects; obj++){
time_per_write = (opts.time_write >= 3 && obj == opts.num_objects);
assert(!(time_per_object && time_per_write));
- /* generate the OID (may be deferred) */
- switch(opts.dist) {
- case SEQ:
- oid = (uint64_t) obj;
- oid_l = triton_uint128_from_uint64(oid);
- break;
- case ALLOC:
- /* defer to allocation time */
- break;
- default:
- assert(0);
- }
- /* create or alloc the object */
- if (opts.dist == SEQ)
- /* attempted creation is OK here as a hacky check for existence */
- tret = remote_triton_rpc_rosd_create(0, oid,
- opts.replication_factor, 0);
- else if (opts.dist == ALLOC) {
- /* choose a random server to allocate from then alloc */
- tret = triton_random64(rng, &rand_id);
- rand_serv_idx = rand_id % nnodes;
- if (!triton_is_error(tret)) {
- rand_serv_str = system_state_get(nodelist[rand_serv_idx],
- "addr");
- if (rand_serv_str != NULL) {
- tret = triton_mercury_addr_lookup(rand_serv_str,
- &rand_serv_addr);
- if (!triton_is_error(tret))
- tret = remote_triton_rpc_rosd_alloc(rand_serv_addr, 0,
- 1, opts.replication_factor, 0, &oid);
- free(rand_serv_str);
- }
- else
- tret = TRITON_ERR_UNKNOWN;
- }
- }
- else
- assert(0);
- if (triton_error_equal(tret, TRITON_ERR_EXIST)){
- char * str = triton_uint128_to_string(oid_l);
- fprintf(stderr, "Object %s exists, need to delete manually for "
- "the time being\n", str);
- triton_error_destroy(tret);
- free(str);
- return 1;
- }
- else if (triton_is_error(tret)){
- triton_error_print(tret, "triton-mkdat: failed to create object");
- triton_error_destroy(tret);
- return 1;
- }
+ oid = oids[obj];
+ if (opts.echo)
+ printf("0x%lx\n", oid);
if (time_per_object){
clock_gettime(CLOCK_MONOTONIC, &ts);
- times[obj-1] = tsToS(ts);
+ times[obj] = tsToS(ts);
}
for (fork = 1; fork <= opts.num_forks; fork++){
for (write_nr = 0; write_nr < opts.writes_per_fork; write_nr++){
@@ -290,6 +433,7 @@ __blocking int aesop_main(int argc, char **argv){
if(triton_is_error(tret)) {
triton_error_print(tret, "remote_triton_rpc_rosd_write()");
triton_error_destroy(tret);
+ triton_mercury_engine_finalize();
return 1;
}
else if (time_per_write){
@@ -301,7 +445,7 @@ __blocking int aesop_main(int argc, char **argv){
}
if (time_per_object){
clock_gettime(CLOCK_MONOTONIC, &ts);
- times[obj-1] = tsToS(ts) - times[obj-1];
+ times[obj] = tsToS(ts) - times[obj];
}
}
@@ -375,7 +519,7 @@ static int parse_args(int argc, char **argv){
int ret;
for (;;) {
- c = getopt_long(argc, argv, "ho:r:f:w:s:Fd:tp:", long_opts,
+ c = getopt_long(argc, argv, "heo:r:f:w:s:Fd:tp:", long_opts,
&longindex);
if (c == -1)
break;
@@ -384,16 +528,17 @@ static int parse_args(int argc, char **argv){
* here */
switch(longindex) {
case 0: c = 'h'; break;
- case 1: c = 'o'; break;
- case 2: c = 'r'; break;
- case 3: c = 'f'; break;
- case 4: c = 'r'; break;
- case 5: c = 'w'; break;
- case 6: c = 's'; break;
- case 7: c = 'F'; break;
- case 8: c = 'd'; break;
- case 9: c = 't'; break;
- case 10: c = 'p'; break;
+ case 1: c = 'e'; break;
+ case 2: c = 'o'; break;
+ case 3: c = 'r'; break;
+ case 4: c = 'f'; break;
+ case 5: c = 'r'; break;
+ case 6: c = 'w'; break;
+ case 7: c = 's'; break;
+ case 8: c = 'F'; break;
+ case 9: c = 'd'; break;
+ case 10: c = 't'; break;
+ case 11: c = 'p'; break;
default: c = '?'; break;
}
}
@@ -402,6 +547,9 @@ static int parse_args(int argc, char **argv){
case 'h':
puts(usage_str);
return 1;
+ case 'e':
+ opts.echo = 1;
+ break;
case 'o':
ret = get_ll_suff("num-objects", optarg, &opts.num_objects);
if (ret) return 1;
@@ -432,10 +580,12 @@ static int parse_args(int argc, char **argv){
opts.fill = 1;
break;
case 'd':
- if (strncmp("seq", optarg, 3) == 0)
+ if (strcmp("seq", optarg) == 0)
opts.dist = SEQ;
- else if (strncmp("alloc", optarg, 5) == 0)
- opts.dist = ALLOC;
+ else if (strcmp("alloc-striped", optarg) == 0)
+ opts.dist = ALLOC_STRIPED;
+ else if (strcmp("alloc", optarg) == 0)
+ opts.dist = ALLOC_RANDOM;
else{
fprintf(stderr,
"unexpected object-dist: %s see -h | --help\n",
diff --git a/code/src/admin-tools/triton-show-placement.ae b/code/src/admin-tools/triton-show-placement.ae
index d60f711..65443a9 100644
--- a/code/src/admin-tools/triton-show-placement.ae
+++ b/code/src/admin-tools/triton-show-placement.ae
@@ -51,7 +51,7 @@ __blocking int aesop_main(int argc, char **argv)
oid = triton_uint128_from_string(argv[2]);
- tret = triton_place_lookup_dump(oid.l, closest, 3);
+ tret = triton_place_lookup_dump(oid.l, closest, 3, NULL);
if(triton_is_error(tret))
{
triton_error_print(tret, "triton_place_lookup_dump()");
diff --git a/code/src/asg/asg-internal.ae b/code/src/asg/asg-internal.ae
index 1127059..af49791 100644
--- a/code/src/asg/asg-internal.ae
+++ b/code/src/asg/asg-internal.ae
@@ -519,7 +519,7 @@ static int generate_cli_server_list_random(
if (triton_is_error(tret))
return -1;
else {
- tret = triton_place_lookup(oid, &nodes[obj], 1);
+ tret = triton_place_lookup(oid, &nodes[obj], 1, NULL);
if (triton_is_error(tret))
return -1;
}
@@ -528,35 +528,39 @@ static int generate_cli_server_list_random(
}
/* helper: hash a list of servers using the placement algorithm */
-static int generate_cli_server_list_placement_random(
+static int generate_cli_server_list_placement_random_uniq(
asg_size_t num_objects,
- triton_node_t *nodes){
+ asg_size_t replication_factor,
+ triton_node_t *nodes,
+ triton_place_ctx ctx){
/* TODO: how to handle replication factor aside from env hack??? */
const char * replication_factor_env;
- int replication_factor;
triton_ret_t tret;
-
- replication_factor = 0;
- replication_factor_env = getenv("TRITON_ASG_RF");
- if (replication_factor_env){
- if (0 == sscanf(replication_factor_env, "%d", &replication_factor)){
- /* simply ignore rather than returning something of interest */
- replication_factor = 0;
+ int rf_int = (int) replication_factor;
+ assert(rf_int >= 0);
+
+ if (rf_int == 0) {
+ replication_factor_env = getenv("TRITON_ASG_RF");
+ if (replication_factor_env){
+ if (replication_factor_env != NULL) {
+ /* failure's fine - rf_int just won't be filled */
+ sscanf(replication_factor_env, "%d", &rf_int);
+ if (rf_int < 0) rf_int = 0;
+ }
+ }
+ else {
+ /* at this point, we should have the server default replication
+ * factor */
+ assert(rosd_default_replication_factor != -1);
+ rf_int = rosd_default_replication_factor;
}
- }
-
- /* we don't know the replication_factor - at this point, we should have it
- * from the server */
- if (replication_factor == 0) {
- assert(rosd_default_replication_factor != -1);
- replication_factor = (int) rosd_default_replication_factor;
}
tret = triton_place_gen_random_unique_set(asg_rng, (int) num_objects,
- replication_factor, nodes);
+ rf_int, nodes, ctx);
if (triton_is_error(tret)) {
triton_error_print(tret,
- "generate_cli_server_list_placement_random()\n");
+ "generate_cli_server_list_placement_random_uniq()\n");
return -1;
}
else
@@ -566,17 +570,25 @@ static int generate_cli_server_list_placement_random(
/* helper for alloc_object_set - returns NULL on failure */
static triton_node_t* generate_cli_server_list(
asg_size_t num_objects,
- int is_cli_unique) {
+ asg_size_t replication_factor,
+ int is_cli_unique,
+ triton_place_ctx *ctx) {
int rc;
triton_node_t *ret = malloc(num_objects * sizeof(*ret));
if (ret == NULL) return NULL;
- if (is_cli_unique)
- rc = generate_cli_server_list_placement_random(num_objects, ret);
- else
+ if (is_cli_unique) {
+ *ctx = triton_place_make_ctx();
+ assert(*ctx != NULL);
+ rc = generate_cli_server_list_placement_random_uniq(num_objects,
+ replication_factor, ret, *ctx);
+ }
+ else {
rc = generate_cli_server_list_random(num_objects, ret);
+ *ctx = NULL;
+ }
if (rc != 0) {
free(ret);
@@ -603,28 +615,29 @@ __blocking int asg_i_alloc_object_set(
int num_obj_per_serv;
asg_size_t i;
+ triton_place_ctx ctx = NULL;
#define NOT_SUPPORTED(etype) \
- fprintf(stderr, "Error: " #etype " currently not supported for alloc\n")
+ fprintf(stderr, "Error: " #etype " currently not supported for alloc\n");\
+ return ASG_ERR_OTHER;
/* check flag - not all supported */
triton_node_t *nodelist;
switch(flag) {
case ASG_EXT_ALLOC_DEFAULT:
- nodelist = generate_cli_server_list(num_objects, 0);
+ nodelist = generate_cli_server_list(num_objects,
+ replication_factor, 0, &ctx);
break;
case ASG_EXT_ALLOC_CLI_UNIQUE_SERVERS:
- nodelist = generate_cli_server_list(num_objects, 1);
+ nodelist = generate_cli_server_list(num_objects,
+ replication_factor, 1, &ctx);
break;
case ASG_EXT_ALLOC_SVR_UNIQUE_SERVERS:
- NOT_SUPPORTED(ASG_EXT_ALLOC_SVR_UNIQUE_SERVERS);
- return ASG_ERR_OTHER;
+ NOT_SUPPORTED(ASG_EXT_ALLOC_SVR_UNIQUE_SERVERS)
case ASG_EXT_ALLOC_TWO_CHOICE:
- NOT_SUPPORTED(ASG_EXT_ALLOC_SVR_UNIQUE_SERVERS);
- return ASG_ERR_OTHER;
+ NOT_SUPPORTED(ASG_EXT_ALLOC_SVR_UNIQUE_SERVERS)
default:
NOT_SUPPORTED(UNKNOWN);
- return ASG_ERR_OTHER;
}
#undef NOT_SUPPORTED
@@ -638,8 +651,9 @@ __blocking int asg_i_alloc_object_set(
for (i = 0; i < num_objects; i++) {
if (i == num_objects-1 ||
!triton_node_equal(nodelist[i], nodelist[i+1])) {
- remote_triton_rpc_rosd_alloc(&nodelist[i], container, num_objects,
- replication_factor, flag, objects);
+ remote_triton_rpc_rosd_alloc(&nodelist[i], container,
+ num_obj_per_serv, (int) replication_factor,
+ 0, ctx, objects);
num_obj_per_serv = 1;
}
else /* not last server && nodes are equal */
diff --git a/code/src/placement/Makefile.subdir b/code/src/placement/Makefile.subdir
index 933924a..9ee4392 100644
--- a/code/src/placement/Makefile.subdir
+++ b/code/src/placement/Makefile.subdir
@@ -4,8 +4,7 @@ src_libtriton_a_SOURCES += \
src/placement/placement-1d.c \
src/placement/placement-multiring.c \
src/placement/placement-method.h \
- src/placement/placement-common.h \
- src/placement/placement-common.c
+ src/placement/placement-method.c
AE_SRC += \
src/placement/placement.ae
diff --git a/code/src/placement/placement-1d.c b/code/src/placement/placement-1d.c
index 0a1be50..843dc9e 100644
--- a/code/src/placement/placement-1d.c
+++ b/code/src/placement/placement-1d.c
@@ -8,12 +8,12 @@
#include "src/common/triton-debug.h"
#include "src/placement/placement.h"
#include "src/placement/placement-method.h"
-#include "src/placement/placement-common.h"
static triton_ret_t lookup_1d_euclid(
uint64_t oid,
triton_node_t* closest_nodes,
int closest_nodes_count,
+ triton_place_ctx ctx,
int dump_flag);
static triton_ret_t initialize_1d(
const char* config_params,
@@ -23,11 +23,13 @@ static triton_ret_t gen_random_unique_set_1d(
triton_random_t *rng,
int num_objects,
int replication_factor,
- triton_node_t *nodelist);
+ triton_node_t *nodelist,
+ triton_place_ctx ctx);
static triton_ret_t gen_random_oid_1d(
triton_random_t *rng,
triton_node_t *node,
- uint64_t *oid);
+ uint64_t *oid,
+ triton_place_ctx ctx);
static void finalize_1d(void);
static int triton_node_1d_cmp(const void* a, const void* b);
@@ -35,6 +37,7 @@ static int nearest_cmp(const void* key, const void *member);
struct triton_placement_method triton_placement_1d =
{
+ .type = PLACE_1D,
.name = "1d",
.lookup = lookup_1d_euclid,
.initialize = initialize_1d,
@@ -57,6 +60,7 @@ static triton_ret_t lookup_1d_euclid(
uint64_t oid,
triton_node_t* closest_nodes,
int closest_nodes_count,
+ triton_place_ctx ctx,
int dump_flag)
{
int i;
@@ -159,16 +163,18 @@ static triton_ret_t gen_random_unique_set_1d(
triton_random_t *rng,
int num_objects,
int replication_factor,
- triton_node_t *nodelist) {
+ triton_node_t *nodelist,
+ triton_place_ctx ctx) {
return gen_random_unique_set_novirt(
&triton_placement_1d,
- rng, num_objects, replication_factor, nodelist);
+ rng, num_objects, replication_factor, nodelist, ctx);
}
static triton_ret_t gen_random_oid_1d(
triton_random_t *rng,
triton_node_t *node,
- uint64_t *oid) {
+ uint64_t *oid,
+ triton_place_ctx ctx) {
triton_ret_t tret;
const struct node_1d *pnode;
struct node_1d dummy_node; /* just for the comparison */
diff --git a/code/src/placement/placement-common.c b/code/src/placement/placement-common.c
deleted file mode 100644
index 351118b..0000000
--- a/code/src/placement/placement-common.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * (C) 2015 The University of Chicago
- *
- * See COPYRIGHT in top-level directory.
- */
-
-#include "src/placement/placement-common.h"
-
-triton_ret_t gen_random_unique_set_novirt(
- struct triton_placement_method *method,
- triton_random_t *rng,
- int num_objects,
- int replication_factor,
- triton_node_t *nodelist){
- uint64_t oid;
- triton_ret_t tret;
- triton_node_t *nodelist_tmp;
- int i, node;
- int num_objects_total = num_objects * replication_factor;
-
- /* simply choose a random oid for the start point */
- tret = triton_random64(rng, &oid);
- if (triton_is_error(tret))
- return tret;
-
- /* do a lookup to get the set of unique nodes (guaranteed by the above
- * conditional), then filter out the ones holding replicas */
- nodelist_tmp =
- malloc(num_objects_total * sizeof(*nodelist_tmp));
- if (nodelist_tmp == NULL)
- return TRITON_ERR_NOMEM;
- tret = method->lookup(oid, nodelist_tmp, num_objects_total, 0);
- if (triton_is_error(tret)){
- free(nodelist_tmp);
- return tret;
- }
- else {
- node = 0;
- for (i = 0; i < num_objects_total; i+=replication_factor)
- nodelist[node++] = nodelist_tmp[i];
- }
-
- /* success */
- free(nodelist_tmp);
- return TRITON_SUCCESS;
-}
diff --git a/code/src/placement/placement-common.h b/code/src/placement/placement-common.h
deleted file mode 100644
index 31f7fc2..0000000
--- a/code/src/placement/placement-common.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * (C) 2015 The University of Chicago
- *
- * See COPYRIGHT in top-level directory.
- */
-
-#ifndef PLACEMENT_COMMON_H
-#define PLACEMENT_COMMON_H
-
-#include "src/common/triton-error.h"
-#include "src/common/node.h"
-#include "src/placement/placement-method.h"
-
-/* create a randomly-selected set of unique servers, with the assumption that
- * the lookup function provided cannot produce duplicates for well-formed
- * inputs (ie the method doesn't use virtual nodes)
- *
- * feasibility checking assumed done by the individual placement methods and
- * the lookup function provided */
-triton_ret_t gen_random_unique_set_novirt(
- struct triton_placement_method *method,
- triton_random_t *rng,
- int num_objects,
- int replication_factor,
- triton_node_t *nodelist);
-
-#endif /* end of include guard: PLACEMENT_COMMON_H */
diff --git a/code/src/placement/placement-method.c b/code/src/placement/placement-method.c
new file mode 100644
index 0000000..7e7e5c2
--- /dev/null
+++ b/code/src/placement/placement-method.c
@@ -0,0 +1,117 @@
+/*
+ * (C) 2015 The University of Chicago
+ *
+ * See COPYRIGHT in top-level directory.
+ */
+
+#include "src/placement/placement-method.h"
+
+triton_ret_t gen_random_unique_set_novirt(
+ struct triton_placement_method *method,
+ triton_random_t *rng,
+ int num_objects,
+ int replication_factor,
+ triton_node_t *nodelist,
+ triton_place_ctx ctx){
+ uint64_t oid;
+ triton_ret_t tret;
+ triton_node_t *nodelist_tmp;
+ int i, node;
+ int num_objects_total = num_objects * replication_factor;
+
+ /* simply choose a random oid for the start point */
+ tret = triton_random64(rng, &oid);
+ if (triton_is_error(tret))
+ return tret;
+
+ /* do a lookup to get the set of unique nodes (guaranteed by the above
+ * conditional), then filter out the ones holding replicas */
+ nodelist_tmp =
+ malloc(num_objects_total * sizeof(*nodelist_tmp));
+ if (nodelist_tmp == NULL)
+ return TRITON_ERR_NOMEM;
+ tret = method->lookup(oid, nodelist_tmp, num_objects_total, ctx, 0);
+ if (triton_is_error(tret)){
+ free(nodelist_tmp);
+ return tret;
+ }
+ else {
+ node = 0;
+ for (i = 0; i < num_objects_total; i+=replication_factor)
+ nodelist[node++] = nodelist_tmp[i];
+ }
+
+ /* success */
+ free(nodelist_tmp);
+ return TRITON_SUCCESS;
+}
+
+/* make/destroy context is here so we have the structure def here */
+
+triton_place_ctx triton_place_make_ctx(void) {
+ triton_place_ctx c = malloc(sizeof(*c));
+ if (c != NULL)
+ c->type = PLACE_UNINITIALIZED;
+ return c;
+}
+
+void triton_place_clear_ctx(triton_place_ctx ctx) {
+ ctx->type = PLACE_UNINITIALIZED;
+}
+
+void triton_place_destroy_ctx(triton_place_ctx ctx) {
+ free(ctx);
+}
+
+int hg_proc_triton_place_ctx(hg_proc_t proc, triton_place_ctx *ctx) {
+ int ret = HG_SUCCESS;
+ int type;
+
+ switch(hg_proc_get_op(proc)) {
+ case HG_ENCODE:
+ if (*ctx != NULL && (*ctx)->type != PLACE_UNINITIALIZED) {
+ type = (*ctx)->type; /* make compiler happy */
+ ret = hg_proc_int32_t(proc, &type);
+ if (ret == HG_SUCCESS && (*ctx)->type == PLACE_MRH)
+ ret = hg_proc_int32_t(proc, &(*ctx)->u.ctx_mrh.ring);
+ break;
+ }
+ else {
+ /* put in the uninit dummy type to indicate not sending */
+ type = PLACE_UNINITIALIZED;
+ ret = hg_proc_int32_t(proc, &type);
+ }
+ break;
+ case HG_DECODE:
+ ret = hg_proc_int32_t(proc, &type);
+ if (ret == HG_SUCCESS && type != PLACE_UNINITIALIZED) {
+ *ctx = triton_place_make_ctx();
+ assert(*ctx != NULL);
+ (*ctx)->type = type;
+ if (type == PLACE_MRH)
+ ret = hg_proc_int32_t(proc, &(*ctx)->u.ctx_mrh.ring);
+ }
+ else
+ *ctx = NULL;
+ break;
+ case HG_FREE:
+ if (*ctx != NULL) {
+ free(*ctx);
+ *ctx = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ if (ret != HG_SUCCESS)
+ HG_LOG_ERROR("Proc error: triton_place_ctx");
+ return ret;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
diff --git a/code/src/placement/placement-method.h b/code/src/placement/placement-method.h
index b89c1b4..bcc28be 100644
--- a/code/src/placement/placement-method.h
+++ b/code/src/placement/placement-method.h
@@ -4,14 +4,41 @@
#include "src/common/triton-error.h"
#include "src/common/node.h"
#include "src/common/triton-random.h"
+#include "src/placement/placement.h"
+
+/* Define the allocation contexts for the implemented placement methods.
+ * Can't think of a better place for these for the time being */
+
+enum triton_placement_method_type {
+ PLACE_1D,
+ PLACE_MRH,
+ PLACE_UNINITIALIZED
+};
+
+/* nothing needed for the time being */
+struct triton_place_ctx_1d {};
+
+struct triton_place_ctx_mrh {
+ int ring;
+};
+
+struct _triton_place_ctx {
+ enum triton_placement_method_type type;
+ union {
+ struct triton_place_ctx_1d ctx_1d;
+ struct triton_place_ctx_mrh ctx_mrh;
+ } u;
+};
struct triton_placement_method
{
+ enum triton_placement_method_type type;
const char* name;
triton_ret_t (*lookup)(
uint64_t oid,
triton_node_t* closest_nodes,
int closest_nodes_count,
+ triton_place_ctx ctx,
int dump_flag);
triton_ret_t (*initialize)(
const char* config_params,
@@ -21,14 +48,31 @@ struct triton_placement_method
triton_random_t *rng,
int num_objects,
int replication_factor,
- triton_node_t *nodelist);
+ triton_node_t *nodelist,
+ triton_place_ctx ctx);
triton_ret_t (*gen_random_oid)(
triton_random_t *rng,
triton_node_t *node,
- uint64_t *oid);
+ uint64_t *oid,
+ triton_place_ctx ctx);
void (*finalize)(void);
};
+/*** Placement-independent helper functions ***/
+
+/* create a randomly-selected set of unique servers, with the assumption that
+ * the lookup function provided cannot produce duplicates for well-formed
+ * inputs (ie the method doesn't use virtual nodes)
+ *
+ * feasibility checking assumed done by the individual placement methods and
+ * the lookup function provided */
+triton_ret_t gen_random_unique_set_novirt(
+ struct triton_placement_method *method,
+ triton_random_t *rng,
+ int num_objects,
+ int replication_factor,
+ triton_node_t *nodelist,
+ triton_place_ctx ctx);
#endif
diff --git a/code/src/placement/placement-multiring.c b/code/src/placement/placement-multiring.c
index d6ff267..8c4e030 100644
--- a/code/src/placement/placement-multiring.c
+++ b/code/src/placement/placement-multiring.c
@@ -10,12 +10,12 @@
#include "src/common/node.h"
#include "src/placement/placement.h"
#include "src/placement/placement-method.h"
-#include "src/placement/placement-common.h"
static triton_ret_t lookup_mring(
uint64_t oid,
triton_node_t* closest_nodes,
int closest_nodes_count,
+ triton_place_ctx ctx,
int dump_flag);
static triton_ret_t initialize_mring(
const char* config_params,
@@ -25,17 +25,20 @@ static triton_ret_t gen_random_unique_set_mring(
triton_random_t *rng,
int num_objects,
int replication_factor,
- triton_node_t *nodelist);
+ triton_node_t *nodelist,
+ triton_place_ctx ctx);
static triton_ret_t gen_random_oid_mring(
triton_random_t *rng,
triton_node_t *node,
- uint64_t *oid);
+ uint64_t *oid,
+ triton_place_ctx ctx);
static void finalize_mring(void);
static int triton_node_mring_cmp(const void* a, const void* b);
static int nearest_cmp(const void* key, const void *member);
struct triton_placement_method triton_placement_mring =
{
+ .type = PLACE_MRH,
.name = "multiring",
.lookup = lookup_mring,
.initialize = initialize_mring,
@@ -64,6 +67,7 @@ static triton_ret_t lookup_mring(
uint64_t oid,
triton_node_t* closest_nodes,
int closest_nodes_count,
+ triton_place_ctx ctx,
int dump_flag)
{
int ring;
@@ -154,6 +158,11 @@ static triton_ret_t lookup_mring(
}
}
+ /* set the context if needed */
+ if (ctx != NULL) {
+ ctx->type = PLACE_MRH;
+ ctx->u.ctx_mrh.ring = ring;
+ }
return(TRITON_SUCCESS);
}
@@ -256,16 +265,60 @@ static triton_ret_t gen_random_unique_set_mring(
triton_random_t *rng,
int num_objects,
int replication_factor,
- triton_node_t *nodelist){
- return gen_random_unique_set_novirt(
- &triton_placement_mring,
- rng, num_objects, replication_factor, nodelist);
+ triton_node_t *nodelist,
+ triton_place_ctx ctx){
+ if (ctx == NULL || ctx->type != PLACE_MRH)
+ return gen_random_unique_set_novirt(
+ &triton_placement_mring,
+ rng, num_objects, replication_factor, nodelist, ctx);
+
+ /* basically the same logic as the novirt call, except explicitly pick a
+ * ring */
+ uint64_t oid, oid_min, oid_max;
+ triton_ret_t tret;
+ triton_node_t *nodelist_tmp;
+ int i, node;
+ int num_objects_total = num_objects * replication_factor;
+ int ring = ctx->u.ctx_mrh.ring;
+
+ tret = triton_random64(rng, &oid);
+ if (triton_is_error(tret))
+ return tret;
+
+ /* do a lookup to get the set of unique nodes (guaranteed by the above
+ * conditional), then filter out the ones holding replicas */
+ nodelist_tmp =
+ malloc(num_objects_total * sizeof(*nodelist_tmp));
+ if (nodelist_tmp == NULL)
+ return TRITON_ERR_NOMEM;
+
+ /* modulate the oid to look up by the ring */
+ oid_min = g_oids_per_ring * ring;
+ if (ring == g_num_rings-1)
+ oid_max = UINT64_MAX;
+ else
+ oid_max = g_oids_per_ring * (ring+1);
+
+ oid = oid % (oid_max-oid_min) + oid_min;
+
+ tret = lookup_mring(oid, nodelist_tmp, num_objects_total, NULL, 0);
+ if (triton_is_error(tret)){
+ free(nodelist_tmp);
+ return tret;
+ }
+ else {
+ node = 0;
+ for (i = 0; i < num_objects_total; i+=replication_factor)
+ nodelist[node++] = nodelist_tmp[i];
+ }
+ return tret;
}
static triton_ret_t gen_random_oid_mring(
triton_random_t *rng,
triton_node_t *node,
- uint64_t *oid) {
+ uint64_t *oid,
+ triton_place_ctx ctx) {
triton_ret_t tret;
const struct node_mrh *ring;
const struct node_mrh *pnode;
@@ -280,14 +333,27 @@ static triton_ret_t gen_random_oid_mring(
return TRITON_ERR_UNKNOWN;
else if (*oid == 0) (*oid)++;
else if (*oid == UINT64_MAX) (*oid)--;
+ if (ctx != NULL) {
+ int r = (*oid) / g_oids_per_ring;
+ if (r == g_num_rings) r--;
+ ctx->type = PLACE_MRH;
+ ctx->u.ctx_mrh.ring = r;
+ }
return TRITON_SUCCESS;
}
/* choose a random ring, then basically do the same 1d calculation
* (unfortunately, since 1d and multiring use different data structures,
* can't share the implementation in a non-C++ template way) */
- tret = triton_random32(rng, &uring);
- uring = uring % (uint32_t)g_num_rings;
+ if (ctx != NULL && ctx->type == PLACE_MRH &&
+ ctx->u.ctx_mrh.ring < g_num_rings && ctx->u.ctx_mrh.ring >= 0)
+ uring = ctx->u.ctx_mrh.ring;
+ else {
+ if (ctx != NULL)
+ triton_place_clear_ctx(ctx);
+ tret = triton_random32(rng, &uring);
+ uring = uring % (uint32_t)g_num_rings;
+ }
ring = g_rings[uring];
/* unlike 1d, gotta track which oids we're generating for */
@@ -335,6 +401,11 @@ static triton_ret_t gen_random_oid_mring(
*oid = oid_mod - end_noids;
}
*oid += oid_offset;
+ /* only set if we didn't read from it */
+ if (ctx != NULL && ctx->type != PLACE_MRH) {
+ ctx->type = PLACE_MRH;
+ ctx->u.ctx_mrh.ring = uring;
+ }
return TRITON_SUCCESS;
}
}
diff --git a/code/src/placement/placement.ae b/code/src/placement/placement.ae
index 2d52d1f..f81d904 100644
--- a/code/src/placement/placement.ae
+++ b/code/src/placement/placement.ae
@@ -26,18 +26,20 @@ static char* g_placement_params = NULL;
triton_ret_t triton_place_lookup(uint64_t oid,
triton_node_t* closest_nodes,
- int closest_nodes_count)
+ int closest_nodes_count,
+ triton_place_ctx ctx)
{
return(method_array[method_idx]->lookup(oid,
- closest_nodes, closest_nodes_count, 0));
+ closest_nodes, closest_nodes_count, ctx, 0));
}
triton_ret_t triton_place_lookup_dump(uint64_t oid,
triton_node_t* closest_nodes,
- int closest_nodes_count)
+ int closest_nodes_count,
+ triton_place_ctx ctx)
{
return(method_array[method_idx]->lookup(oid,
- closest_nodes, closest_nodes_count, 1));
+ closest_nodes, closest_nodes_count, ctx, 1));
}
@@ -45,17 +47,19 @@ triton_ret_t triton_place_gen_random_unique_set(
triton_random_t *rng,
int num_objects,
int replication_factor,
- triton_node_t *nodelist){
+ triton_node_t *nodelist,
+ triton_place_ctx ctx){
assert(num_objects > 0 && replication_factor > 0);
return(method_array[method_idx]->gen_random_unique_set(rng, num_objects,
- replication_factor, nodelist));
+ replication_factor, nodelist, ctx));
}
triton_ret_t triton_place_gen_random_oid(
triton_random_t *rng,
triton_node_t *node,
- uint64_t *oid){
- return method_array[method_idx]->gen_random_oid(rng, node, oid);
+ uint64_t *oid,
+ triton_place_ctx ctx){
+ return method_array[method_idx]->gen_random_oid(rng, node, oid, ctx);
}
static triton_ret_t placement_params_updater(const char *key, const char *value)
@@ -152,7 +156,6 @@ void triton_place_finalize(void)
triton_mutex_unlock(&module_lock);
}
-
/*
* Local Variables:
* c-basic-offset: 4
diff --git a/code/src/placement/placement.h b/code/src/placement/placement.h
index 0755a9f..9a847af 100644
--- a/code/src/placement/placement.h
+++ b/code/src/placement/placement.h
@@ -4,33 +4,63 @@
#include "src/common/triton-error.h"
#include "src/common/node.h"
#include "src/common/triton-random.h"
+#include <mercury_proc.h>
+
+/* algorithm-specific information about placement operations used. This is
+ * needed so we can do some client-server logic requiring info about the
+ * placement algorithm (e.g. allocating objects on specific rings) */
+typedef struct _triton_place_ctx * triton_place_ctx;
+
+triton_place_ctx triton_place_make_ctx(void);
+void triton_place_clear_ctx(triton_place_ctx ctx);
+void triton_place_destroy_ctx(triton_place_ctx ctx);
+/* encode/decode context in messages */
+int hg_proc_triton_place_ctx(hg_proc_t proc, triton_place_ctx *ctx);
+
+/* NOTE: in the following functions, a NULL context can be used to indicate
+ * an unknown / don't care context */
triton_ret_t triton_place_initialize(void);
+/* strictly sets ctx if non-NULL */
triton_ret_t triton_place_lookup(uint64_t oid,
triton_node_t* closest_nodes,
- int closest_nodes_count);
+ int closest_nodes_count,
+ triton_place_ctx ctx);
triton_ret_t triton_place_lookup_dump(uint64_t oid,
triton_node_t* closest_nodes,
- int closest_nodes_count);
+ int closest_nodes_count,
+ triton_place_ctx ctx);
/* attempt to find a server set by which no objects and their corresponding
* servers overlap.
*
- * if non-unique is required, then users can simply call triton_place_lookup
- * with random oids */
+ * if non-unique is preferred, then users can simply call triton_place_lookup
+ * with random oids
+ *
+ * if ctx is non-null, in an uninitialized state, or not of the same type as the
+ * resulting algorithm, then write the placement metadata from the generation.
+ * If it is initialized and of the same type, then use the metadata in the
+ * unique set generation semantics (i.e. alloc to a specific ring) */
triton_ret_t triton_place_gen_random_unique_set(
triton_random_t *rng,
int num_objects,
int replication_factor,
- triton_node_t *nodelist);
+ triton_node_t *nodelist,
+ triton_place_ctx ctx);
-/* generate a random OID for the provided node */
+/* generate a random OID for the provided node
+ * if ctx is non-null, in an uninitialized state, and of the same type as the
+ * resulting algorithm, then write the placement metadata from the generation.
+ * If it is initialized and not of the same type, then write the metadata.
+ * If it is initialized and of the same type, then use the metadata in the
+ * unique set generation semantics */
triton_ret_t triton_place_gen_random_oid(
triton_random_t *rng,
triton_node_t *node,
- uint64_t *oid);
+ uint64_t *oid,
+ triton_place_ctx ctx);
void triton_place_finalize(void);
diff --git a/code/src/replicated-osd/rosd-alloc.ae b/code/src/replicated-osd/rosd-alloc.ae
index fb0ff6e..a56000d 100644
--- a/code/src/replicated-osd/rosd-alloc.ae
+++ b/code/src/replicated-osd/rosd-alloc.ae
@@ -41,6 +41,7 @@ MERCURY_GEN_PROC(triton_rpc_rosd_alloc_in_t,
((uint32_t)(replication_factor))
((uint32_t)(num_objects))
((uint32_t)(flags))
+ ((triton_place_ctx)(ctx))
((hg_bulk_t)(bulk_handle))) /* for the returned objects */
static hg_id_t rpc_rosd_alloc_id;
@@ -139,7 +140,7 @@ static __blocking triton_ret_t triton_rpc_rosd_alloc(hg_handle_t handle)
triton_debug(triton_dbg_rosd, "triton_rpc_rosd_alloc: "
"attempt %d\n", oid_attempt);
b_tret = triton_place_gen_random_oid(alloc_rng, &self,
- &oid);
+ &oid, in.ctx);
if (triton_is_error(b_tret)) {
triton_error_msg("triton_rpc_rosd_alloc: "
"failed to gen random oid\n");
@@ -291,13 +292,13 @@ __blocking triton_ret_t remote_triton_rpc_rosd_alloc(
uint32_t num_objects,
uint32_t replicas,
uint32_t flags,
+ triton_place_ctx ctx,
uint64_t *objects)
{
triton_rpc_rosd_alloc_out_t out;
triton_rpc_rosd_alloc_in_t in;
triton_ret_t tret;
uint64_t bulk_sz;
- char * svr_string;
hg_handle_t handle;
@@ -305,6 +306,7 @@ __blocking triton_ret_t remote_triton_rpc_rosd_alloc(
in.flags = flags;
in.replication_factor = replicas;
in.num_objects = num_objects;
+ in.ctx = ctx;
bulk_sz = (size_t)num_objects * sizeof(*objects);
triton_mercury_run_rpc_with_bulk(addr, rpc_rosd_alloc_id, handle, &in,
@@ -318,8 +320,6 @@ __blocking triton_ret_t remote_triton_rpc_rosd_alloc(
HG_Destroy(handle);
- free(svr_string);
-
return(tret);
}
diff --git a/code/src/replicated-osd/rosd.ae b/code/src/replicated-osd/rosd.ae
index 4162dd2..4188ec5 100644
--- a/code/src/replicated-osd/rosd.ae
+++ b/code/src/replicated-osd/rosd.ae
@@ -205,7 +205,7 @@ triton_ret_t triton_oid_to_addrs(
* the array to only include nodes that are valid targets.
*/
- tret = triton_place_lookup(oid, target_nodes, replication_factor);
+ tret = triton_place_lookup(oid, target_nodes, replication_factor, NULL);
if(triton_is_error(tret))
{
free(target_nodes);
diff --git a/code/src/replicated-osd/rosd.hae b/code/src/replicated-osd/rosd.hae
index 0e5b587..9746d5f 100644
--- a/code/src/replicated-osd/rosd.hae
+++ b/code/src/replicated-osd/rosd.hae
@@ -8,6 +8,7 @@
#include "src/common/triton-error.h"
#include "src/replicated-osd/buffer-mgmt.hae"
+#include "src/placement/placement.h"
/* for requests that should be fanned out from the master for replication */
#define ROSD_FLAG_FANOUT 1
@@ -145,6 +146,7 @@ __blocking triton_ret_t remote_triton_rpc_rosd_alloc(
uint32_t num_objects,
uint32_t replicas,
uint32_t flags,
+ triton_place_ctx ctx,
uint64_t *objects);
#endif /* __ROSD_HAE */
hooks/post-receive
--
1
0
branch, trac-323-sos, updated. 3773521d77cfd3ce0c85e949dc33bc32f9947f9d
by noreply@mcs.anl.gov 29 Jan '15
by noreply@mcs.anl.gov 29 Jan '15
29 Jan '15
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, trac-323-sos has been updated
via 3773521d77cfd3ce0c85e949dc33bc32f9947f9d (commit)
via aad07f24df26e3d68d5e1bf8689def5627499c3e (commit)
via 74f1852a25b1e8ce8fbe581ea5456ea067d4eda8 (commit)
via dc8cc3faa3b4560ed8a4b14228e66748a0112766 (commit)
via 7ecbfbd34cafc8c4f17253d4f9b9866c0718fa1e (commit)
via 96ff00a0303a8fdaf950998c5fafb71cbde94556 (commit)
via 3f701489bab1ba35cff7c8b1448f6dc2e882cb28 (commit)
via d7931a9582162266337bb086b1122f2dfbeaf41e (commit)
from a3afa3e064e856e26837666e622c5f0019d411b2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 3773521d77cfd3ce0c85e949dc33bc32f9947f9d
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Thu Jan 29 10:48:16 2015 -0600
update mkdat utility to allow random oid allocation
commit aad07f24df26e3d68d5e1bf8689def5627499c3e
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Thu Jan 29 10:33:11 2015 -0600
pbranch impl of object allocation
commit 74f1852a25b1e8ce8fbe581ea5456ea067d4eda8
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Thu Jan 29 10:05:01 2015 -0600
impl of placement-based random oid generation
+ miscellaneous placement fixes
commit dc8cc3faa3b4560ed8a4b14228e66748a0112766
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Thu Jan 29 10:01:09 2015 -0600
initstate_r doesn't like garbage input apparently...
commit 7ecbfbd34cafc8c4f17253d4f9b9866c0718fa1e
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Wed Jan 28 10:43:17 2015 -0600
misc. fixes to rng
commit 96ff00a0303a8fdaf950998c5fafb71cbde94556
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Wed Jan 28 09:17:01 2015 -0600
spit out hoss config values in cfg script
commit 3f701489bab1ba35cff7c8b1448f6dc2e882cb28
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Wed Jan 28 08:25:16 2015 -0600
bad address-of when computing hoss ids
commit d7931a9582162266337bb086b1122f2dfbeaf41e
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Wed Jan 28 08:22:58 2015 -0600
fixes to RNG for mutex'ing
-----------------------------------------------------------------------
Summary of changes:
code/scripts/simple-mgmt/generate-config.sh | 3 +-
code/src/admin-tools/triton-mkdat.ae | 78 +++++++--
code/src/common/triton-random.c | 68 +++++---
code/src/placement/placement-1d.c | 84 ++++++++-
code/src/placement/placement-method.h | 4 +
code/src/placement/placement-multiring.c | 103 ++++++++++-
code/src/placement/placement.ae | 7 +
code/src/placement/placement.h | 14 +-
code/src/replicated-osd/rosd-alloc.ae | 251 ++++++++++++++++++++++++---
code/src/replicated-osd/rosd-create.ae | 7 +-
code/src/replicated-osd/rosd-internal.hae | 5 +
code/src/replicated-osd/rosd-write.ae | 2 +-
code/src/replicated-osd/rosd.hae | 2 +-
13 files changed, 530 insertions(+), 98 deletions(-)
Diff of changes:
diff --git a/code/scripts/simple-mgmt/generate-config.sh b/code/scripts/simple-mgmt/generate-config.sh
index 9093dfd..936def2 100755
--- a/code/scripts/simple-mgmt/generate-config.sh
+++ b/code/scripts/simple-mgmt/generate-config.sh
@@ -140,8 +140,7 @@ else
cfg=$(cat <<EOF
triton_debug_masks = $g_mask
triton_debug_file = $g_tdir/triton-server-%TRITON_SERVER_NAME%-log
-triton_tosd_db_path = $g_tdir/triton-server-%TRITON_SERVER_NAME%-meta
-triton_tosd_data_path = $g_tdir/triton-server-%TRITON_SERVER_NAME%-data
+triton_hoss_base_path = $g_tdir/triton-server-%TRITON_SERVER_NAME%-hoss
$g_rf_key = $g_repfactor
EOF
)
diff --git a/code/src/admin-tools/triton-mkdat.ae b/code/src/admin-tools/triton-mkdat.ae
index 48b81a5..d889d7d 100644
--- a/code/src/admin-tools/triton-mkdat.ae
+++ b/code/src/admin-tools/triton-mkdat.ae
@@ -11,6 +11,8 @@
#include "src/remote/core-rpc.hae"
#include "src/common/triton-debug.h"
#include "src/common/triton-bootstrap.hae"
+#include "src/common/triton-random.h"
+#include "src/placement/placement.h"
#include "src/system-state/system-state.hae"
#include "src/replicated-osd/rosd.hae"
@@ -37,6 +39,8 @@ static const char * usage_str =
" -d, --object-dist DIST - distribution of object IDs.\n"
" DIST expected to be one of \"seq\", <TODO: more dists>\n"
" seq - OIDs assigned in increasing order (e.g., 1, 2, 3, ...)\n"
+" alloc - OIDs assigned using the rosd-alloc RPC (one by one,\n"
+" rather than batched). The request is sent to SERVER\n"
" (default - seq)\n"
" -t, --time - time write phase of program, printing to stdout\n"
" NOTE: timing is performed at object-granularity\n"
@@ -55,6 +59,7 @@ static const char * usage_str =
enum object_dist {
SEQ,
+ ALLOC,
};
struct opt_vals{
@@ -150,13 +155,28 @@ __blocking int aesop_main(int argc, char **argv){
return(-1);
}
- size_t buf_size;
- unsigned char * buffer;
+ /* for randomly selecting servers to write to (used */
+ triton_random_t *rng;
+ uint64_t rand_id;
+ triton_node_t *nodelist;
+ int nnodes;
+ char *rand_serv_str;
+ na_addr_t rand_serv_addr;
+ int rand_serv_idx;
+
+ tret = triton_random_create(&rng, 0, NULL, 0);
+ assert(!triton_is_error(tret));
+ tret = system_state_list_nodes("addr", &nodelist, &nnodes);
+ assert(!triton_is_error(tret));
/* allocate a buffer large enough to hold all data in a single write */
+
+ unsigned char * buffer;
+
buffer = malloc(opts.size_per_write);
if (buffer == NULL) {
- fprintf(stderr, "unable to allocate buffer of size %lu\n", buf_size);
+ fprintf(stderr, "unable to allocate buffer of size %lu\n",
+ opts.size_per_write);
return 1;
}
@@ -184,16 +204,45 @@ __blocking int aesop_main(int argc, char **argv){
for (obj = 1; obj <= opts.num_objects; obj++){
time_per_write = (opts.time_write >= 3 && obj == opts.num_objects);
assert(!(time_per_object && time_per_write));
- if (opts.dist == SEQ){
- oid = (uint64_t) obj;
- oid_l = triton_uint128_from_uint64(oid);
+ /* generate the OID (may be deferred) */
+ switch(opts.dist) {
+ case SEQ:
+ oid = (uint64_t) obj;
+ oid_l = triton_uint128_from_uint64(oid);
+ break;
+ case ALLOC:
+ /* defer to allocation time */
+ break;
+ default:
+ assert(0);
}
- else {
- assert(0);
+ /* create or alloc the object */
+ if (opts.dist == SEQ)
+ /* attempted creation is OK here as a hacky check for existence */
+ tret = remote_triton_rpc_rosd_create(0, oid,
+ opts.replication_factor, 0);
+ else if (opts.dist == ALLOC) {
+ /* choose a random server to allocate from then alloc */
+ tret = triton_random64(rng, &rand_id);
+ rand_serv_idx = rand_id % nnodes;
+ if (!triton_is_error(tret)) {
+ rand_serv_str = system_state_get(nodelist[rand_serv_idx],
+ "addr");
+ if (rand_serv_str != NULL) {
+ tret = triton_mercury_addr_lookup(rand_serv_str,
+ &rand_serv_addr);
+ if (!triton_is_error(tret))
+ tret = remote_triton_rpc_rosd_alloc(rand_serv_addr, 0,
+ 1, opts.replication_factor, 0, &oid);
+ free(rand_serv_str);
+ }
+ else
+ tret = TRITON_ERR_UNKNOWN;
+ }
}
- /* attempted creation is OK here */
- tret = remote_triton_rpc_rosd_create(0, oid, opts.replication_factor,
- 0);
+ else
+ assert(0);
+
if (triton_error_equal(tret, TRITON_ERR_EXIST)){
char * str = triton_uint128_to_string(oid_l);
fprintf(stderr, "Object %s exists, need to delete manually for "
@@ -203,7 +252,7 @@ __blocking int aesop_main(int argc, char **argv){
return 1;
}
else if (triton_is_error(tret)){
- triton_error_print(tret, "remote_triton_rpc_rosd_create()");
+ triton_error_print(tret, "triton-mkdat: failed to create object");
triton_error_destroy(tret);
return 1;
}
@@ -383,9 +432,10 @@ static int parse_args(int argc, char **argv){
opts.fill = 1;
break;
case 'd':
- if (strncmp("seq", optarg, 3) == 0) {
+ if (strncmp("seq", optarg, 3) == 0)
opts.dist = SEQ;
- }
+ else if (strncmp("alloc", optarg, 5) == 0)
+ opts.dist = ALLOC;
else{
fprintf(stderr,
"unexpected object-dist: %s see -h | --help\n",
diff --git a/code/src/common/triton-random.c b/code/src/common/triton-random.c
index 18c98b1..26d2fba 100644
--- a/code/src/common/triton-random.c
+++ b/code/src/common/triton-random.c
@@ -13,15 +13,20 @@
#include "src/common/triton-random.h"
#include "src/common/self.h"
#include "src/common/triton-error.h"
+#include "triton-config.h"
#if RAND_MAX < INT_MAX
#warning "RAND_MAX < INT_MAX - numbers resulting from triton-random may be of very poor quality!"
#endif
+/* TODO: parameterize this */
+static const size_t STATESZ = 256;
+
struct triton_random_t {
triton_mutex_t mutex;
int use_mutex;
#ifdef HAVE_RANDOM_R
+ void * state_buf;
struct random_data rd;
#else
unsigned int seed;
@@ -41,7 +46,7 @@ triton_ret_t triton_random_create(struct triton_random_t **rng, int use_mutex,
triton_random_t *r;
/* initialize the data structure */
- r = malloc(sizeof(*r));
+ r = calloc(1, sizeof(*r));
if (r == NULL)
return TRITON_ERR_NOMEM;
@@ -83,7 +88,15 @@ triton_ret_t triton_random_create(struct triton_random_t **rng, int use_mutex,
/* initialize the rng */
#ifdef HAVE_RANDOM_R
- srandom_r(seed, &r->rd);
+ r->state_buf = malloc(STATESZ);
+ if (r->state_buf == NULL) {
+ free(r);
+ return TRITON_ERR_NOMEM;
+ }
+ else {
+ rc = initstate_r(seed, r->state_buf, STATESZ, &r->rd);
+ assert(rc == 0);
+ }
#else
r->seed = seed;
#endif
@@ -97,6 +110,9 @@ triton_ret_t triton_random_create(struct triton_random_t **rng, int use_mutex,
void triton_random_destroy(triton_random_t *rng) {
if (rng->use_mutex)
triton_mutex_destroy(&rng->mutex);
+#ifdef HAVE_RANDOM_R
+ free(rng->state_buf);
+#endif
free(rng);
}
@@ -120,23 +136,27 @@ static triton_ret_t triton_random32_unsafe(
rand_res_bit = rand_r(&rng->seed);
#endif
- if (!rc) {
+ if (rc != 0) {
return TRITON_ERR_UNKNOWN;
}
else
- *result = (uint32_t) (rand_res | (rand_res_bit<<31));
+ *result = ((uint32_t)rand_res) | (((uint32_t)rand_res_bit)<<31);
return TRITON_SUCCESS;
}
triton_ret_t triton_random32(triton_random_t *rng, uint32_t *result) {
- int rc;
triton_ret_t tret;
- rc = triton_mutex_lock(&rng->mutex);
- if (!rc)
- return TRITON_ERR_UNKNOWN;
- else
- tret = triton_random32_unsafe(rng, result);
- triton_mutex_unlock(&rng->mutex);
+
+ if (rng->use_mutex) {
+ int rc = triton_mutex_lock(&rng->mutex);
+ if (rc != 0)
+ return TRITON_ERR_UNKNOWN;
+ }
+
+ tret = triton_random32_unsafe(rng, result);
+
+ if (rng->use_mutex)
+ triton_mutex_unlock(&rng->mutex);
return tret;
}
@@ -144,18 +164,22 @@ triton_ret_t triton_random64(triton_random_t *rng, uint64_t *result) {
uint32_t upper, lower;
int rc;
triton_ret_t tret;
- rc = triton_mutex_lock(&rng->mutex);
- if (!rc)
- return TRITON_ERR_UNKNOWN;
- else {
- tret = triton_random32_unsafe(rng, &lower);
- if (tret == TRITON_SUCCESS) {
- tret = triton_random32_unsafe(rng, &upper);
- if (tret == TRITON_SUCCESS)
- *result = (((uint64_t)upper) << 32) | lower;
- }
+
+ if (rng->use_mutex) {
+ rc = triton_mutex_lock(&rng->mutex);
+ if (rc != 0)
+ return TRITON_ERR_UNKNOWN;
+ }
+
+ tret = triton_random32_unsafe(rng, &lower);
+ if (tret == TRITON_SUCCESS) {
+ tret = triton_random32_unsafe(rng, &upper);
+ if (tret == TRITON_SUCCESS)
+ *result = (((uint64_t)upper) << 32) | (uint64_t)lower;
}
- triton_mutex_unlock(&rng->mutex);
+
+ if (rng->use_mutex)
+ triton_mutex_unlock(&rng->mutex);
return tret;
}
diff --git a/code/src/placement/placement-1d.c b/code/src/placement/placement-1d.c
index 7111998..0a1be50 100644
--- a/code/src/placement/placement-1d.c
+++ b/code/src/placement/placement-1d.c
@@ -24,6 +24,11 @@ static triton_ret_t gen_random_unique_set_1d(
int num_objects,
int replication_factor,
triton_node_t *nodelist);
+static triton_ret_t gen_random_oid_1d(
+ triton_random_t *rng,
+ triton_node_t *node,
+ uint64_t *oid);
+
static void finalize_1d(void);
static int triton_node_1d_cmp(const void* a, const void* b);
static int nearest_cmp(const void* key, const void *member);
@@ -34,7 +39,8 @@ struct triton_placement_method triton_placement_1d =
.lookup = lookup_1d_euclid,
.initialize = initialize_1d,
.finalize = finalize_1d,
- .gen_random_unique_set = gen_random_unique_set_1d
+ .gen_random_unique_set = gen_random_unique_set_1d,
+ .gen_random_oid = gen_random_oid_1d
};
struct node_1d
@@ -119,7 +125,6 @@ static triton_ret_t initialize_1d(
assert(initial_node_array);
assert(initial_node_array_size > 0);
- assert(config_params == NULL || strlen(config_params) == 0);
g_node_array = malloc(initial_node_array_size*sizeof(*g_node_array));
if(!g_node_array)
@@ -160,10 +165,72 @@ static triton_ret_t gen_random_unique_set_1d(
rng, num_objects, replication_factor, nodelist);
}
+static triton_ret_t gen_random_oid_1d(
+ triton_random_t *rng,
+ triton_node_t *node,
+ uint64_t *oid) {
+ triton_ret_t tret;
+ const struct node_1d *pnode;
+ struct node_1d dummy_node; /* just for the comparison */
+
+ /* single node - just use full address space */
+ if (g_node_array_size == 1) {
+ tret = triton_random64(rng, oid);
+ if (triton_is_error(tret))
+ return TRITON_ERR_UNKNOWN;
+ else if (*oid == 0) (*oid)++;
+ else if (*oid == UINT64_MAX) (*oid)--;
+ return TRITON_SUCCESS;
+ }
+
+ /* find node
+ * - bsearch should always succeed as we're directly using server ids */
+ dummy_node.id = node->l;
+ pnode = bsearch(&dummy_node, g_node_array, g_node_array_size,
+ sizeof(*g_node_array), triton_node_1d_cmp);
+
+ if (!triton_node_equal(pnode->node_id, *node))
+ return TRITON_ERR_NOTFOUND;
+ else {
+ uint64_t oid_r;
+ tret = triton_random64(rng, &oid_r);
+ if (triton_is_error(tret))
+ return tret;
+ /* generate bounds, accounting for weird wraparound */
+ if (pnode->idx > 0) {
+ /* bound is [x,y) (we don't hold our own ids) */
+ uint64_t oid_min = (pnode-1)->id;
+ uint64_t oid_max = pnode->id;
+ if (oid_min == oid_max-1)
+ return TRITON_ERR_NOTFOUND;
+ else
+ *oid = oid_r % (oid_max-oid_min) + oid_min;
+ }
+ else { /* idx == 0 */
+ /* oid ranges - last node id to the end, beginning to this node id.
+ * ie [id_prev, MAX), [1, id) */
+ uint64_t prev_id = g_node_array[g_node_array_size-1].id;
+ uint64_t end_noids = UINT64_MAX - prev_id;
+ uint64_t start_noids = pnode->id - 1;
+ uint64_t oid_mod;
+ /* this can only happen in a very silly case (last id = MAX, first
+ * id = 1) */
+ if (end_noids == 0 && start_noids == 0)
+ return TRITON_ERR_NOTFOUND;
+ oid_mod = oid_r % (end_noids+start_noids);
+ if (oid_mod < end_noids)
+ *oid = oid_mod + prev_id;
+ else
+ *oid = oid_mod - end_noids;
+ }
+ return TRITON_SUCCESS;
+ }
+}
+
static int triton_node_1d_cmp(const void* a, const void* b)
{
- uint64_t aa = *(const uint64_t*)a;
- uint64_t bb = *(const uint64_t*)b;
+ uint64_t aa = ((const struct node_1d*)a)->id;
+ uint64_t bb = ((const struct node_1d*)b)->id;
if (aa < bb) return -1;
else if (aa == bb) return 0;
else return 1;
@@ -172,18 +239,19 @@ static int triton_node_1d_cmp(const void* a, const void* b)
/* find the server with the largest ID less than the object ID */
static int nearest_cmp(const void* key, const void *member)
{
- const struct node_1d* svr = member;
- const uint64_t oid = *(const uint64_t*) key;
- int cmp = triton_node_1d_cmp(key, member);
+ struct node_1d dummy;
+ dummy.id = *(const uint64_t*) key;
+ int cmp = triton_node_1d_cmp(&dummy, member);
if (cmp < 0)
return -1;
else if (cmp > 0)
{
+ const struct node_1d* svr = member;
/* are we on the last server already? */
if (svr->idx == (g_node_array_size-1))
return 0;
/* is the oid also larger than the next server's id? */
- else if (oid > g_node_array[svr->idx+1].id)
+ else if (dummy.id > g_node_array[svr->idx+1].id)
return 1;
}
diff --git a/code/src/placement/placement-method.h b/code/src/placement/placement-method.h
index 6c9b64c..b89c1b4 100644
--- a/code/src/placement/placement-method.h
+++ b/code/src/placement/placement-method.h
@@ -22,6 +22,10 @@ struct triton_placement_method
int num_objects,
int replication_factor,
triton_node_t *nodelist);
+ triton_ret_t (*gen_random_oid)(
+ triton_random_t *rng,
+ triton_node_t *node,
+ uint64_t *oid);
void (*finalize)(void);
};
diff --git a/code/src/placement/placement-multiring.c b/code/src/placement/placement-multiring.c
index 9561a7c..d6ff267 100644
--- a/code/src/placement/placement-multiring.c
+++ b/code/src/placement/placement-multiring.c
@@ -7,6 +7,7 @@
#include <jenkins-hash.h>
#include "src/common/triton-debug.h"
+#include "src/common/node.h"
#include "src/placement/placement.h"
#include "src/placement/placement-method.h"
#include "src/placement/placement-common.h"
@@ -25,6 +26,10 @@ static triton_ret_t gen_random_unique_set_mring(
int num_objects,
int replication_factor,
triton_node_t *nodelist);
+static triton_ret_t gen_random_oid_mring(
+ triton_random_t *rng,
+ triton_node_t *node,
+ uint64_t *oid);
static void finalize_mring(void);
static int triton_node_mring_cmp(const void* a, const void* b);
static int nearest_cmp(const void* key, const void *member);
@@ -35,7 +40,8 @@ struct triton_placement_method triton_placement_mring =
.lookup = lookup_mring,
.initialize = initialize_mring,
.finalize = finalize_mring,
- .gen_random_unique_set = gen_random_unique_set_mring
+ .gen_random_unique_set = gen_random_unique_set_mring,
+ .gen_random_oid = gen_random_oid_mring
};
struct node_mrh
@@ -255,33 +261,110 @@ static triton_ret_t gen_random_unique_set_mring(
&triton_placement_mring,
rng, num_objects, replication_factor, nodelist);
}
+
+static triton_ret_t gen_random_oid_mring(
+ triton_random_t *rng,
+ triton_node_t *node,
+ uint64_t *oid) {
+ triton_ret_t tret;
+ const struct node_mrh *ring;
+ const struct node_mrh *pnode;
+ uint32_t uring;
+ uint64_t oid_offset;
+ int i;
+
+ /* single node - just use full address space */
+ if (g_num_servers == 1) {
+ tret = triton_random64(rng, oid);
+ if (triton_is_error(tret))
+ return TRITON_ERR_UNKNOWN;
+ else if (*oid == 0) (*oid)++;
+ else if (*oid == UINT64_MAX) (*oid)--;
+ return TRITON_SUCCESS;
+ }
+
+ /* choose a random ring, then basically do the same 1d calculation
+ * (unfortunately, since 1d and multiring use different data structures,
+ * can't share the implementation in a non-C++ template way) */
+ tret = triton_random32(rng, &uring);
+ uring = uring % (uint32_t)g_num_rings;
+ ring = g_rings[uring];
+
+ /* unlike 1d, gotta track which oids we're generating for */
+ oid_offset = uring * g_oids_per_ring;
+
+ /* find node - not one-to-one since virt ids are used, so need O(n) loop */
+ for (i = 0; i < g_num_servers; i++){
+ if (triton_node_equal(*node, ring[i].node_id))
+ break;
+ }
+ if (i == g_num_servers)
+ return TRITON_ERR_NOTFOUND;
+ else {
+ uint64_t oid_r;
+ pnode = &ring[i];
+ tret = triton_random64(rng, &oid_r);
+ if (triton_is_error(tret))
+ return tret;
+ /* NOTE: virt ids are 0..g_oids_per_ring(+leftover),
+ * so can for the most part just treat the ring calcs as a 1d ring
+ * then adjust at the end */
+ if (pnode->idx > 0) {
+ /* bound is [x,y) (we don't hold our own ids) */
+ uint64_t oid_min = (pnode-1)->virt_id;
+ uint64_t oid_max = pnode->virt_id;
+ if (oid_min == oid_max-1)
+ return TRITON_ERR_NOTFOUND;
+ *oid = oid_r % (oid_max-oid_min) + oid_min;
+ }
+ else { /* idx == 0 */
+ /* oid ranges - last node id to the end, beginning to this node id.
+ * ie [id_prev, MAX), [1, id) */
+ uint64_t num_oids = g_oids_per_ring +
+ ((uring+1 == g_num_rings) ? UINT64_MAX % g_oids_per_ring : 0);
+ uint64_t prev_id = ring[g_num_servers-1].virt_id;
+ uint64_t end_noids = num_oids - prev_id;
+ uint64_t start_noids = pnode->virt_id - 1;
+ uint64_t oid_mod;
+ if (end_noids == 0 && start_noids == 0)
+ return TRITON_ERR_NOTFOUND;
+ oid_mod = oid_r % (end_noids+start_noids);
+ if (oid_mod < end_noids)
+ *oid = oid_mod + prev_id;
+ else
+ *oid = oid_mod - end_noids;
+ }
+ *oid += oid_offset;
+ return TRITON_SUCCESS;
+ }
+}
+
/* NOTE: currently zeroing out upper bits for comparison until we remove
* 128-bit ids */
static int triton_node_mring_cmp(const void* a, const void* b)
{
- uint64_t aa = *(const uint64_t*)a;
- uint64_t bb = *(const uint64_t*)b;
+ uint64_t aa = ((const struct node_mrh*)a)->virt_id;
+ uint64_t bb = ((const struct node_mrh*)b)->virt_id;
if (aa < bb) return -1;
else if (aa == bb) return 0;
else return 1;
}
-/* find the server with the largest virtual ID less than the object ID
- * NOTE: currently zeroing out upper bits for comparison until we remove
- * 128-bit ids */
+/* find the server with the largest virtual ID less than the object ID */
static int nearest_cmp(const void* key, const void *member)
{
- const struct node_mrh* svr = member;
- const uint64_t oid = *(const uint64_t*) key;
- int cmp = triton_node_mring_cmp(key, member);
+ struct node_mrh dummy;
+ dummy.virt_id = *(const uint64_t*) key;
+ int cmp = triton_node_mring_cmp(&dummy, member);
if (cmp < 0)
return -1;
else if (cmp > 0){
+ const struct node_mrh* svr = member;
/* are we on the last server already? */
if (svr->idx == (g_num_servers-1))
return 0;
/* is the oid also larger than the next server's id? */
- else if (oid > g_rings[svr->ring][svr->idx+1].virt_id)
+ else if (dummy.virt_id > g_rings[svr->ring][svr->idx+1].virt_id)
return 1;
}
diff --git a/code/src/placement/placement.ae b/code/src/placement/placement.ae
index e873f9a..2d52d1f 100644
--- a/code/src/placement/placement.ae
+++ b/code/src/placement/placement.ae
@@ -51,6 +51,13 @@ triton_ret_t triton_place_gen_random_unique_set(
replication_factor, nodelist));
}
+triton_ret_t triton_place_gen_random_oid(
+ triton_random_t *rng,
+ triton_node_t *node,
+ uint64_t *oid){
+ return method_array[method_idx]->gen_random_oid(rng, node, oid);
+}
+
static triton_ret_t placement_params_updater(const char *key, const char *value)
{
assert(!strcmp(key, "triton_placement_params"));
diff --git a/code/src/placement/placement.h b/code/src/placement/placement.h
index fd43705..0755a9f 100644
--- a/code/src/placement/placement.h
+++ b/code/src/placement/placement.h
@@ -15,12 +15,8 @@ triton_ret_t triton_place_lookup_dump(uint64_t oid,
triton_node_t* closest_nodes,
int closest_nodes_count);
-/* the uint64_t is the seed val to use in case the placement algo needs a
- * source of entropy to start up the process
- *
- * if gen_unique_nodes is non-zero, then attempt to find a server set by which
- * no objects and their replicas overlap. replication_factor is only used in
- * this case
+/* attempt to find a server set by which no objects and their corresponding
+ * servers overlap.
*
* if non-unique is required, then users can simply call triton_place_lookup
* with random oids */
@@ -30,6 +26,12 @@ triton_ret_t triton_place_gen_random_unique_set(
int replication_factor,
triton_node_t *nodelist);
+/* generate a random OID for the provided node */
+triton_ret_t triton_place_gen_random_oid(
+ triton_random_t *rng,
+ triton_node_t *node,
+ uint64_t *oid);
+
void triton_place_finalize(void);
#endif
diff --git a/code/src/replicated-osd/rosd-alloc.ae b/code/src/replicated-osd/rosd-alloc.ae
index 88fb277..fb0ff6e 100644
--- a/code/src/replicated-osd/rosd-alloc.ae
+++ b/code/src/replicated-osd/rosd-alloc.ae
@@ -10,17 +10,27 @@
#include <triton-hash.h>
#include <mercury_macros.h>
#include <mercury_proc.h>
+#include <hoss.hae>
#include "src/replicated-osd/rosd.hae"
#include "src/replicated-osd/rosd-internal.hae"
#include "src/common/triton-debug.h"
#include "src/common/self.h"
+#include "src/common/triton-random.h"
#include "src/placement/placement.h"
#include "src/system-state/system-state.hae"
#include "src/remote/mercury-engine.hae"
#include "src/remote/mercury-encode.h"
#include "src/system-state/system-state.hae"
+/* Number of times we'll try allocating random oids
+ * TODO: make this a parameter */
+static const int max_tries = 32;
+
+static triton_random_t *alloc_rng = NULL;
+static triton_mutex_t alloc_mutex = TRITON_MUTEX_INITIALIZER;
+
+extern struct hoss_ctx *g_hoss_ctx;
/* Mercury RPC structures for rosd_alloc */
MERCURY_GEN_PROC(triton_rpc_rosd_alloc_out_t,
@@ -42,14 +52,25 @@ static __blocking triton_ret_t triton_rpc_rosd_alloc(hg_handle_t handle)
triton_rpc_rosd_alloc_in_t in;
na_addr_t addr_array[2];
uint32_t actual_rep_factor;
- uint32_t i;
int my_position;
- uint64_t *oids;
+ uint64_t *oids = NULL;
+ uint32_t oid_gen_count;
+ triton_node_t self;
+ uint64_t niid;
+ triton_ret_t pwait_ret;
+ /* return information */
+ hg_bulk_t bulk_handle = HG_BULK_NULL;
+ struct hg_info *info = NULL;
+ size_t bulk_size;
+ int rc;
triton_debug(triton_dbg_rosd, "Called triton_rpc_rosd_alloc()\n");
triton_mercury_get_input(handle, &in, &out);
+ assert(!(in.flags & ROSD_FLAG_FANOUT));
+ in.flags |= ROSD_FLAG_CHAIN;
+
triton_debug(triton_dbg_rosd, "triton_rpc_rosd_alloc() params: "
"container:%lu num_objects:%d, "
"replication_factor:%d, flags:%d\n",
@@ -57,36 +78,215 @@ static __blocking triton_ret_t triton_rpc_rosd_alloc(hg_handle_t handle)
out.tret = TRITON_SUCCESS;
+ /* TODO: generate real NIIDs */
+ niid = 0;
+
/* replication_factor of 0 -> defer to system default */
actual_rep_factor = (in.replication_factor)
? in.replication_factor : rosd_default_replication_factor;
- /* generate set of oids to use */
- oids = malloc(in.num_objects * sizeof(*oids));
- /* TODO: query SOS to produce valid oids and ensure they exist via a magic
- * fork write */
- out.tret = TRITON_ERR_NOT_IMPLEMENTED;
+ /* generate set of oids to use, and set to a dummy */
+ bulk_size = in.num_objects * sizeof(*oids);
+ oids = malloc(bulk_size);
+ if (oids == NULL) {
+ out.tret = TRITON_ERR_NOMEM;
+ goto response;
+ }
- /* TODO: forward request __as a create__ to replica servers.
- * The real solution would likely involve culling the list to aggregate
- * requests using pbranches (different oids with the same primary may
- * have different replica servers) and differentiating between chain
- * and fan replication.
- * It should be similar to how the ROSD create code works. */
+ info = HG_Get_info(handle);
+ /* init the bulk handle before the crazy */
+ rc = HG_Bulk_create(info->hg_bulk_class, 1, (void**)&oids,
+ &bulk_size, HG_BULK_READ_ONLY, &bulk_handle);
+ if (rc != HG_SUCCESS) {
+ triton_error_msg("HG_Bulk_create() failure\n");
+ out.tret = TRITON_ERR_NOMEM;
+ goto response;
+ }
+
+ self = triton_self_node();
+
+ /* TODO: query HOSS to produce valid oids rather than the nicely hacky RNG
+ * approach! */
+ /* TODO: what's the correct return code for a retry-based failure? */
+ /* TODO: undo ALL object creates if there's a failure? */
+ /* TODO: mutex approach is somewhat reasonable, but relies on some implicit
+ * local storage behavior (namely, that create races are handled for
+ * identical oids). Should probably think of a better way of doing this */
+ /* TODO: lots of debug output here. Clean it up later on */
+ oid_gen_count = 0;
+ pwait_ret = TRITON_SUCCESS;
+ pwait {
+ pprivate triton_ret_t b_tret;
+ pprivate uint32_t i, j;
+ pprivate int rc_p;
+ pprivate uint64_t oid;
+ pprivate int oid_attempt;
+ pprivate int num_place_servers_check;
+ pprivate int my_position;
+ /* only need mine and the immediate next, if necessary */
+ pprivate na_addr_t addr_array[2];
+
+ for (i = 0; i < in.num_objects; i++){
+ pbranch {
+ if (triton_is_error(pwait_ret)) {
+ triton_error_msg("triton_rpc_rosd_alloc: "
+ "detected branch error\n");
+ pbreak;
+ }
+
+ oid_attempt = 0;
+ while (oid_attempt < max_tries) {
+ triton_debug(triton_dbg_rosd, "triton_rpc_rosd_alloc: "
+ "attempt %d\n", oid_attempt);
+ b_tret = triton_place_gen_random_oid(alloc_rng, &self,
+ &oid);
+ if (triton_is_error(b_tret)) {
+ triton_error_msg("triton_rpc_rosd_alloc: "
+ "failed to gen random oid\n");
+ pwait_ret = triton_error_dup(b_tret);
+ pbreak;
+ }
+ else
+ triton_debug(triton_dbg_rosd, "triton_rpc_rosd_alloc: "
+ "attempting to alloc oid %lu\n", oid);
+
+ /* check our generated oid against others
+ * Either:
+ * - it doesn't exist, and no other threads trying to create.
+ * A-OK
+ * - it doesn't exist, but other threads are in the process
+ * of creating it. We have a race, but only one will
+ * succeed the subsequent create call, so we're OK here
+ * (extremely unlikely to occur)
+ * - it does exist, make another one */
+ rc_p = triton_mutex_lock(&alloc_mutex);
+ if (rc_p != 0) {
+ triton_error_msg("triton_rpc_rosd_alloc: "
+ "unable to lock for obj check\n");
+ pwait_ret = TRITON_ERR_UNKNOWN;
+ pbreak;
+ }
+ for (j = 0; j < oid_gen_count; j++){
+ if (oids[j] == oid) {
+ oid_attempt++;
+ break;
+ }
+ }
+ if (j < oid_gen_count) {
+ triton_mutex_unlock(&alloc_mutex);
+ break;
+ }
+ else
+ triton_mutex_unlock(&alloc_mutex);
+
+ /* before attempting the create, sanity check the
+ * oid placement and set up the next server to contact */
+ if (actual_rep_factor > 1) {
+ num_place_servers_check =
+ (actual_rep_factor > 1) ? 2 : 1;
+ b_tret = triton_oid_to_addrs(oid,
+ num_place_servers_check, &my_position,
+ addr_array);
+ if (triton_is_error(b_tret)) {
+ pwait_ret = triton_error_dup(b_tret);
+ triton_error_msg("triton_rpc_rosd_alloc: "
+ "failed to map oid %lu to "
+ "replica servers\n", oid);
+ pbreak;
+ }
+ /* otherwise, placement algo is busted */
+ assert(my_position == 0);
+ }
+
+ /* attempt the create */
+ b_tret = rosd_create_local_storage(0, oid,
+ actual_rep_factor, niid);
+ if (triton_is_error(b_tret) && b_tret != TRITON_ERR_EXIST) {
+ triton_error_msg("triton_rpc_rosd_alloc: "
+ "non-eexist error\n");
+ pwait_ret = triton_error_dup(b_tret);
+ pbreak;
+ }
+ else if (b_tret != TRITON_ERR_EXIST) { /* success */
+ triton_debug(triton_dbg_rosd, "triton_rpc_rosd_alloc: "
+ "succeeded alloc\n");
+ rc_p = triton_mutex_lock(&alloc_mutex);
+ if (rc_p != 0) {
+ triton_error_msg("triton_rpc_rosd_alloc: "
+ "failed to lock\n");
+ pwait_ret = TRITON_ERR_UNKNOWN;
+ pbreak;
+ }
+ oids[oid_gen_count++] = oid;
+ triton_mutex_unlock(&alloc_mutex);
+
+ /* if needed, send an RPC to the next server,
+ * ___as a create___ */
+ if (actual_rep_factor > 1) {
+ /* this create is expected to succeed, otherwise we
+ * have big consistency problems */
+ triton_debug(triton_dbg_rosd,
+ "triton_rpc_rosd_alloc: calling create\n");
+ b_tret = __remote_triton_rpc_rosd_create(
+ addr_array[1], in.container, oid,
+ actual_rep_factor, in.flags, 1);
+ if (triton_is_error(b_tret)) {
+ triton_error_msg("triton_rpc_rosd_alloc: "
+ "failed to forward create\n");
+ pwait_ret = triton_error_dup(b_tret);
+ }
+ }
+ else
+ triton_debug(triton_dbg_rosd,
+ "triton_rpc_rosd_alloc: not calling create "
+ "(actual_rep_factor=%u)\n",
+ actual_rep_factor);
+ pbreak;
+ }
+ else /* b_tret == TRITON_ERR_EXIST */
+ oid_attempt++;
+ }
+ if (oid_attempt == max_tries) {
+ triton_error_msg("triton_rpc_rosd_alloc: "
+ "hit max alloc tries\n");
+ pwait_ret = TRITON_ERR_NOMEM;
+ pbreak;
+ }
+ }
+ }
+ }
- if (triton_is_error(out.tret))
+ /* did everything succeed? */
+ if (pwait_ret == TRITON_SUCCESS) {
+ out.num_objects = in.num_objects;
+ rc = hg_rsc_bulk_transfer(info->bulk_context, HG_BULK_PUSH, info->addr,
+ in.bulk_handle, 0, bulk_handle, 0, bulk_size);
+ /* TODO: properly handle cancellation */
+ assert(rc != AE_ERR_CANCELLED);
+ if (rc != HG_SUCCESS) {
+ triton_error_msg("hg_rsc_bulk_transfer() failure.\n");
+ out.tret = TRITON_ERR_UNKNOWN;
+ out.num_objects = 0;
+ }
+ }
+ else {
out.num_objects = 0;
+ out.tret = triton_error_dup(pwait_ret);
+ }
+
+response:
triton_mercury_respond(handle, &out);
- HG_Destroy(handle);
+ if (bulk_handle != HG_BULK_NULL) HG_Bulk_free(bulk_handle);
free(oids);
+ HG_Destroy(handle);
return(TRITON_SUCCESS);
}
TRITON_DEFINE_RPC_HANDLER(triton_rpc_rosd_alloc)
__blocking triton_ret_t remote_triton_rpc_rosd_alloc(
- triton_node_t *dest_node,
+ na_addr_t addr,
uint64_t container,
uint32_t num_objects,
uint32_t replicas,
@@ -96,27 +296,16 @@ __blocking triton_ret_t remote_triton_rpc_rosd_alloc(
triton_rpc_rosd_alloc_out_t out;
triton_rpc_rosd_alloc_in_t in;
triton_ret_t tret;
- na_addr_t addr;
uint64_t bulk_sz;
char * svr_string;
- /* get the mercury address */
- svr_string = system_state_get(*dest_node, "addr");
- if(!svr_string)
- return(TRITON_ERR_UNKNOWN);
- tret = triton_mercury_addr_lookup(svr_string, &addr);
- if(triton_is_error(tret)) {
- free(svr_string);
- return(tret);
- }
-
hg_handle_t handle;
in.container = container;
in.flags = flags;
in.replication_factor = replicas;
in.num_objects = num_objects;
- bulk_sz = (size_t)num_objects * (size_t)replicas * sizeof(uint64_t);
+ bulk_sz = (size_t)num_objects * sizeof(*objects);
triton_mercury_run_rpc_with_bulk(addr, rpc_rosd_alloc_id, handle, &in,
&out, in.bulk_handle, 1, (void**)&objects, &bulk_sz, 0, HG_BULK_WRITE_ONLY);
@@ -137,6 +326,7 @@ __blocking triton_ret_t remote_triton_rpc_rosd_alloc(
void triton_rpc_rosd_alloc_register(void)
{
hg_class_t* hg_class = NULL;
+ triton_ret_t tret;
hg_class = triton_mercury_engine_get_class();
@@ -145,6 +335,11 @@ void triton_rpc_rosd_alloc_register(void)
triton_rpc_rosd_alloc_out_t,
triton_rpc_rosd_alloc_handler);
+ /* initialize my RNG (is this the best place to do this?)... */
+ tret = triton_random_create(&alloc_rng, 1, "rosd-alloc",
+ strlen("rosd-alloc"));
+ assert(!triton_is_error(tret));
+
return;
}
diff --git a/code/src/replicated-osd/rosd-create.ae b/code/src/replicated-osd/rosd-create.ae
index 44b57e0..d350c28 100644
--- a/code/src/replicated-osd/rosd-create.ae
+++ b/code/src/replicated-osd/rosd-create.ae
@@ -39,11 +39,6 @@ static __blocking triton_ret_t rosd_create_do_work(
uint64_t niid,
int from_client_flag);
static int is_usage_error_create(triton_ret_t tret);
-static __blocking triton_ret_t rosd_create_local_storage(
- uint64_t container,
- uint64_t oid,
- uint32_t replication_factor,
- uint64_t niid);
static __blocking triton_ret_t triton_rpc_rosd_create(hg_handle_t handle)
{
@@ -257,7 +252,7 @@ static int is_usage_error_create(triton_ret_t tret)
*
* performs the local steps needed in a replicated create
*/
-static __blocking triton_ret_t rosd_create_local_storage(
+__blocking triton_ret_t rosd_create_local_storage(
uint64_t container,
uint64_t oid,
uint32_t replication_factor,
diff --git a/code/src/replicated-osd/rosd-internal.hae b/code/src/replicated-osd/rosd-internal.hae
index fde0321..76ebdd3 100644
--- a/code/src/replicated-osd/rosd-internal.hae
+++ b/code/src/replicated-osd/rosd-internal.hae
@@ -68,6 +68,11 @@ __blocking triton_ret_t __remote_triton_rpc_rosd_create(
uint32_t flags,
uint32_t expected_position);
+__blocking triton_ret_t rosd_create_local_storage(
+ uint64_t container,
+ uint64_t oid,
+ uint32_t replication_factor,
+ uint64_t niid);
#endif /* __ROSD_INTERNAL_HAE */
diff --git a/code/src/replicated-osd/rosd-write.ae b/code/src/replicated-osd/rosd-write.ae
index abb04a5..30de2d8 100644
--- a/code/src/replicated-osd/rosd-write.ae
+++ b/code/src/replicated-osd/rosd-write.ae
@@ -277,7 +277,7 @@ static __blocking triton_ret_t resolve_replication_factor(
/* go ahead and make the soid */
soid.nids = 3;
- soid.ids = &soid_eids;
+ soid.ids = soid_eids;
soid_eids[0] = in->container;
soid_eids[1] = in->object;
soid_eids[2] = REP_FACTOR_FORK;
diff --git a/code/src/replicated-osd/rosd.hae b/code/src/replicated-osd/rosd.hae
index 649468b..0e5b587 100644
--- a/code/src/replicated-osd/rosd.hae
+++ b/code/src/replicated-osd/rosd.hae
@@ -140,7 +140,7 @@ __blocking triton_ret_t remote_triton_rpc_rosd_reset(
uint64_t *reset_count);
__blocking triton_ret_t remote_triton_rpc_rosd_alloc(
- triton_node_t *dest_node,
+ na_addr_t addr,
uint64_t container,
uint32_t num_objects,
uint32_t replicas,
hooks/post-receive
--
1
0
branch, trac-323-sos, updated. a3afa3e064e856e26837666e622c5f0019d411b2
by noreply@mcs.anl.gov 27 Jan '15
by noreply@mcs.anl.gov 27 Jan '15
27 Jan '15
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, trac-323-sos has been updated
via a3afa3e064e856e26837666e622c5f0019d411b2 (commit)
from 8f46a51b805500d9ae50bc72a6c070725d2f2cf2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a3afa3e064e856e26837666e622c5f0019d411b2
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Tue Jan 27 08:55:59 2015 -0600
allow user-defined entropy mixing in triton_random
we currently have a rng-per-module flavor to our random number needs (currently
asg-alloc-object, later on rosd-alloc-object). Allowing to mix in user-provided
buffers improves the case where multiple triton components need RNG support
with varying levels of granularity.
-----------------------------------------------------------------------
Summary of changes:
code/src/asg/asg-internal.ae | 2 +-
code/src/common/triton-random.c | 5 ++++-
code/src/common/triton-random.h | 8 +++++++-
3 files changed, 12 insertions(+), 3 deletions(-)
Diff of changes:
diff --git a/code/src/asg/asg-internal.ae b/code/src/asg/asg-internal.ae
index bce344f..1127059 100644
--- a/code/src/asg/asg-internal.ae
+++ b/code/src/asg/asg-internal.ae
@@ -79,7 +79,7 @@ __blocking int asg_i_initialize(asg_instance_t *instance,
// initialize random number generator (must be done after "self" hostname
// is initialized)
// want to be thread-safe, so enable mutex usage
- tret = triton_random_create(&asg_rng, 1);
+ tret = triton_random_create(&asg_rng, 1, "asg", strlen("asg"));
if (triton_is_error(tret))
{
triton_error_print(tret, "triton_random_create()");
diff --git a/code/src/common/triton-random.c b/code/src/common/triton-random.c
index 6166ed8..18c98b1 100644
--- a/code/src/common/triton-random.c
+++ b/code/src/common/triton-random.c
@@ -28,7 +28,8 @@ struct triton_random_t {
#endif
};
-triton_ret_t triton_random_create(struct triton_random_t **rng, int use_mutex) {
+triton_ret_t triton_random_create(struct triton_random_t **rng, int use_mutex,
+ const void *mix_buf, int mix_sz) {
/* as an initial seed, hash together the
* current time, the hostname, and the pid into a 32-bit int */
struct timeval t;
@@ -77,6 +78,8 @@ triton_ret_t triton_random_create(struct triton_random_t **rng, int use_mutex) {
seed = bj_hashlittle(&t_us, sizeof(t_us), 0);
seed = bj_hashlittle(&pid, sizeof(pid), seed);
seed = bj_hashlittle(hostname, strlen(hostname), seed);
+ if (mix_buf)
+ seed = bj_hashlittle(mix_buf, mix_sz, seed);
/* initialize the rng */
#ifdef HAVE_RANDOM_R
diff --git a/code/src/common/triton-random.h b/code/src/common/triton-random.h
index c853d6b..5262b95 100644
--- a/code/src/common/triton-random.h
+++ b/code/src/common/triton-random.h
@@ -12,7 +12,13 @@
typedef struct triton_random_t triton_random_t;
-triton_ret_t triton_random_create(triton_random_t **rng, int use_mutex);
+/* create a random number generator, storing the result in *rng.
+ * use_mutex - whether to wrap calls to triton_random32/64 with a mutex
+ * mix_buf, mix_sz - additional source of "entropy" to use. This is simply
+ * to differentiate different triton components initializing at roughly the
+ * same time. NULL, 0 is a valid input - the buffer is not mixed into the seed */
+triton_ret_t triton_random_create(triton_random_t **rng, int use_mutex,
+ const void * mix_buf, int mix_sz);
void triton_random_destroy(triton_random_t *rng);
triton_ret_t triton_random32(triton_random_t *rng, uint32_t *result);
hooks/post-receive
--
1
0
branch, trac-323-sos, updated. 8f46a51b805500d9ae50bc72a6c070725d2f2cf2
by noreply@mcs.anl.gov 27 Jan '15
by noreply@mcs.anl.gov 27 Jan '15
27 Jan '15
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, trac-323-sos has been updated
via 8f46a51b805500d9ae50bc72a6c070725d2f2cf2 (commit)
from 05d497680913912facfe43d815538103cc152e61 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 8f46a51b805500d9ae50bc72a6c070725d2f2cf2
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Tue Jan 27 08:15:23 2015 -0600
hoss-ify rosd-create, re-enable create check in mkdat
-----------------------------------------------------------------------
Summary of changes:
code/src/admin-tools/triton-mkdat.ae | 6 +--
code/src/replicated-osd/rosd-create.ae | 99 ++++++++++++++-----------------
2 files changed, 46 insertions(+), 59 deletions(-)
Diff of changes:
diff --git a/code/src/admin-tools/triton-mkdat.ae b/code/src/admin-tools/triton-mkdat.ae
index 44eaa05..48b81a5 100644
--- a/code/src/admin-tools/triton-mkdat.ae
+++ b/code/src/admin-tools/triton-mkdat.ae
@@ -191,13 +191,9 @@ __blocking int aesop_main(int argc, char **argv){
else {
assert(0);
}
- /* TODO: use probe to figure out object existence. As is, this will
- * lead to partially overwritten objects if they exist. */
- /*
+ /* attempted creation is OK here */
tret = remote_triton_rpc_rosd_create(0, oid, opts.replication_factor,
0);
- */
- tret = TRITON_SUCCESS;
if (triton_error_equal(tret, TRITON_ERR_EXIST)){
char * str = triton_uint128_to_string(oid_l);
fprintf(stderr, "Object %s exists, need to delete manually for "
diff --git a/code/src/replicated-osd/rosd-create.ae b/code/src/replicated-osd/rosd-create.ae
index 3955e48..44b57e0 100644
--- a/code/src/replicated-osd/rosd-create.ae
+++ b/code/src/replicated-osd/rosd-create.ae
@@ -15,6 +15,7 @@
#include "src/remote/mercury-encode.h"
#include "src/system-state/system-state.hae"
+extern struct hoss_ctx* g_hoss_ctx;
/* Mercury RPC structures for rosd_create */
MERCURY_GEN_PROC(triton_rpc_rosd_create_out_t, ((triton_ret_t)(tret)))
@@ -194,7 +195,6 @@ static __blocking triton_ret_t rosd_create_do_work(
/* forward request while simultaneously performing local work */
pwait
{
- pprivate char* oid_str;
pbranch
{
if(my_position < replication_factor -1)
@@ -213,7 +213,6 @@ static __blocking triton_ret_t rosd_create_do_work(
triton_debug(triton_dbg_rosd,
"ROSD local create of oid %lu on %d'th server.\n",
oid, my_position);
- if (oid_str) free(oid_str);
/* perform local operation */
local_tret = rosd_create_local_storage(container, oid,
replication_factor, niid);
@@ -266,61 +265,53 @@ static __blocking triton_ret_t rosd_create_local_storage(
)
{
triton_ret_t tret;
- triton_ret_t tret_tmp;
- int value = 0;
- int64_t obj_offset;
- int64_t size;
- char* buffer_offsets[1];
- triton_node_t self;
-
- self = triton_self_node();
-
- tret = TRITON_ERR_NOT_IMPLEMENTED;
- /* TODO: REPLACEME tret = tosd_create(oid, niid); */
- if(triton_error_equal(tret, TRITON_ERR_NIID_DONE))
- {
- /* this operation is already done */
- triton_error_destroy(tret);
- tret = TRITON_SUCCESS;
- }
-
- if(tret != TRITON_SUCCESS)
- {
- return triton_error_wrap(tret, self, "tosd_create failed");
+ uint32_t ondisk_rep_factor;
+ /* hoss vars, if you couldn't tell */
+ struct hoss_grp *grp;
+ struct hoss_oid soid;
+ struct hoss_record_info ribuf;
+ hoss_eid_t soid_eids[3];
+ hoss_size_t nbytes, info_count;
+ hoss_update_t update_info;
+ int rc, hoss_rc;
+
+ soid.nids = 3;
+ soid.ids = soid_eids;
+ soid_eids[0] = container;
+ soid_eids[1] = oid;
+ soid_eids[2] = REP_FACTOR_FORK;
+
+ rc = hoss_begin(&grp, NULL, 0, g_hoss_ctx);
+ fflush(stdout);
+ if (rc != 0)
+ return TRITON_ERR_IO;
+
+ /* TODO: incorporate versioning information */
+ /* TODO: create's are currently exclusive - we might want non-exclusive so
+ * everything doesn't fail */
+ rc = hoss_read(&soid, 0, 1, 0, 0,
+ &ondisk_rep_factor, sizeof(ondisk_rep_factor),
+ &ribuf, 1, grp, &nbytes, &info_count, &update_info, &hoss_rc);
+ if (rc == 0 && hoss_rc == 0 && nbytes == sizeof(ondisk_rep_factor)) {
+ hoss_end(grp, 1);
+ tret = TRITON_ERR_EXIST;
}
-
- /* store replication factor directly in a data fork */
- obj_offset = 0;
- buffer_offsets[0] = (char*)&replication_factor;
- size = sizeof(replication_factor);
-
- /* NOTE: no need for tracking NIID for this portion of the operation.
- * There is no harm in writing the replication factor twice. We do need
- * to look out for conflicts on the transaction number, though.
- */
- /* TODO: REPLACEME
- tret = tosd_write(oid, REP_FACTOR_FORK, 1, buffer_offsets,
- &size, 1, &obj_offset, &size, 1, TOSD_FLAG_AUTO_TXN, 0, NULL);
- */
- if(tret != TRITON_SUCCESS)
- {
- /* We created the object but weren't able to write its metadata.
- * Give a best effort here to remove the object in order to simplify
- * cleanup later. It's ok if this does not succeed.
- */
- /* TODO: REPLACEME
- tret_tmp = tosd_remove(oid, 0);
- */
- if(tret_tmp != TRITON_SUCCESS)
- {
- triton_error_destroy(tret_tmp);
+ else {
+ rc = hoss_write(&soid, 0, 1, sizeof(replication_factor), 0,
+ 0, 0, &replication_factor, grp, &nbytes, &hoss_rc);
+ if (rc != 0 || hoss_rc != 0) {
+ tret = TRITON_ERR_IO;
+ hoss_end(grp, 0);
+ }
+ else {
+ rc = hoss_end(grp, 1);
+ if (rc != 0 || nbytes != sizeof(ondisk_rep_factor))
+ tret = TRITON_ERR_IO;
+ else
+ tret = TRITON_SUCCESS;
}
- /* don't propagate tret_tmp to the caller; we want the caller to see
- * the original error code instead, not side-effects from cleanup.
- */
}
-
- return(tret);
+ return tret;
}
void triton_rpc_rosd_create_register(void)
hooks/post-receive
--
1
0
branch, trac-323-sos, updated. 05d497680913912facfe43d815538103cc152e61
by noreply@mcs.anl.gov 23 Jan '15
by noreply@mcs.anl.gov 23 Jan '15
23 Jan '15
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, trac-323-sos has been updated
via 05d497680913912facfe43d815538103cc152e61 (commit)
via f41e04213f608a2da32246a2fd45d0c67c01a807 (commit)
via 46cb04fce4ec91ce198a5279b3a1d431e7df549d (commit)
via 32c49be64da778d61c13bddf7444655d2b9cea98 (commit)
via 18908d726932f77de00202922f71a38aee60a63f (commit)
from 071f493b20f6ea57abd54d78da037573f4b53acb (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 05d497680913912facfe43d815538103cc152e61
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Fri Jan 23 18:01:31 2015 -0600
misc write fixes
- bad malloc
- bad init of hoss id on non-primary servers writing the magic fork
commit f41e04213f608a2da32246a2fd45d0c67c01a807
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Fri Jan 23 16:37:35 2015 -0600
fix to replication factor check for forwarding
commit 46cb04fce4ec91ce198a5279b3a1d431e7df549d
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Fri Jan 23 12:38:30 2015 -0600
disable obj create/exist check in mkdat
Need this to do further testing. Besides, "create" and probe are nonfunctional
anyways
commit 32c49be64da778d61c13bddf7444655d2b9cea98
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Fri Jan 23 12:36:30 2015 -0600
sos->hoss name change
commit 18908d726932f77de00202922f71a38aee60a63f
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Fri Jan 23 10:41:59 2015 -0600
configuration - sos->hoss, hoss mandatory
-----------------------------------------------------------------------
Summary of changes:
code/configure.ac | 17 ++----
code/src/admin-tools/triton-mkdat.ae | 5 ++
code/src/replicated-osd/rosd-write.ae | 94 +++++++++++++++++----------------
code/src/replicated-osd/rosd.ae | 7 +--
code/src/replicated-osd/rosd.hae | 4 +-
code/src/server/triton-server.ae | 29 +++++-----
code/src/zeroconf/zeroconf.c | 6 +-
7 files changed, 81 insertions(+), 81 deletions(-)
Diff of changes:
diff --git a/code/configure.ac b/code/configure.ac
index 48f5f80..1e29a5f 100755
--- a/code/configure.ac
+++ b/code/configure.ac
@@ -143,18 +143,11 @@ dnl versions of Berkeley DB
CPPFLAGS="$CPPFLAGS -I$srcdir -I$srcdir/include -I. -D__TRITON_POSIX_LOCKING__ -DDB_DBM_HSEARCH=0"
CFLAGS="$CFLAGS -I$srcdir -I$srcdir/include -I. -D__TRITON_POSIX_LOCKING__ -DDB_DBM_HSEARCH=0"
-dnl optionally link in sos storage component
-AC_ARG_ENABLE(sos,
-[ --enable-sos Turn on support for SOS storage component],
-[if test "x$enableval" = "xyes" ;then
- PKG_CHECK_MODULES([SOS],[sos], [],
- [AC_MSG_ERROR([Could not find working SOS installation!])])
- LIBS="$SOS_LIBS $LIBS"
- CFLAGS="$SOS_CFLAGS $CFLAGS"
- dnl unfortunately pkg-config doesn't separate cppflags/cflags
- CPPFLAGS="$SOS_CPPFLAGS $CPPFLAGS"
- enable_sos=true
-fi], [enable_sos=false])
+dnl link in sos storage component
+PKG_CHECK_MODULES([HOSS],[hoss], [],
+ [AC_MSG_ERROR([Could not find working HOSS installation!])])
+LIBS="$HOSS_LIBS $LIBS"
+CPPFLAGS="$HOSS_CFLAGS $CPPFLAGS"
dnl figure out if we should enable snapshot isolation, either because the
dnl user forced it at configure time or we have a new enough BDB to use it
diff --git a/code/src/admin-tools/triton-mkdat.ae b/code/src/admin-tools/triton-mkdat.ae
index 8bca60d..44eaa05 100644
--- a/code/src/admin-tools/triton-mkdat.ae
+++ b/code/src/admin-tools/triton-mkdat.ae
@@ -191,8 +191,13 @@ __blocking int aesop_main(int argc, char **argv){
else {
assert(0);
}
+ /* TODO: use probe to figure out object existence. As is, this will
+ * lead to partially overwritten objects if they exist. */
+ /*
tret = remote_triton_rpc_rosd_create(0, oid, opts.replication_factor,
0);
+ */
+ tret = TRITON_SUCCESS;
if (triton_error_equal(tret, TRITON_ERR_EXIST)){
char * str = triton_uint128_to_string(oid_l);
fprintf(stderr, "Object %s exists, need to delete manually for "
diff --git a/code/src/replicated-osd/rosd-write.ae b/code/src/replicated-osd/rosd-write.ae
index c5b4c31..abb04a5 100644
--- a/code/src/replicated-osd/rosd-write.ae
+++ b/code/src/replicated-osd/rosd-write.ae
@@ -5,7 +5,7 @@
#include <mercury_macros.h>
#include <mercury_proc.h>
#include <assert.h>
-#include <sos.hae>
+#include <hoss.hae>
#include "src/replicated-osd/rosd.hae"
#include "src/replicated-osd/rosd-internal.hae"
@@ -22,7 +22,7 @@
* keep in flight for a single write operation
*/
extern int64_t rosd_write_xfer_pipeline_depth;
-extern struct sos_ctx* g_sos_ctx;
+extern struct hoss_ctx* g_hoss_ctx;
extern int64_t rosd_write_buffer_size;
/* Mercury RPC structures for rsos_write */
@@ -266,21 +266,28 @@ static __blocking triton_ret_t rosd_write_run_pipeline(
static __blocking triton_ret_t resolve_replication_factor(
triton_rpc_rosd_write_in_t *in)
{
- struct sos_grp *grp;
- struct sos_oid soid;
- sos_eid_t soid_eids[3];
+ struct hoss_grp *grp;
+ struct hoss_oid soid;
+ hoss_eid_t soid_eids[3];
int32_t ondisk_rep_factor;
- sos_size_t nbytes, nrec_infos;
- sos_update_t update_info;
- struct sos_record_info ribuf;
- int ret, sos_rc;
+ hoss_size_t nbytes, nrec_infos;
+ hoss_update_t update_info;
+ struct hoss_record_info ribuf;
+ int ret, hoss_rc;
- /* TODO: check for "CANCELED" return code from sos once supported. In
+ /* go ahead and make the soid */
+ soid.nids = 3;
+ soid.ids = &soid_eids;
+ soid_eids[0] = in->container;
+ soid_eids[1] = in->object;
+ soid_eids[2] = REP_FACTOR_FORK;
+
+ /* TODO: check for "CANCELED" return code from hoss once supported. In
* that case we need to kick out of this function so that it can be
* retried.
*/
- ret = sos_begin(&grp, NULL, 0, g_sos_ctx);
+ ret = hoss_begin(&grp, NULL, 0, g_hoss_ctx);
if(ret != 0)
{
return(TRITON_ERR_IO);
@@ -292,15 +299,9 @@ static __blocking triton_ret_t resolve_replication_factor(
* factor here against what is stored on disk (if present)
*/
- soid.nids = 3;
- soid.ids = soid_eids;
- soid_eids[0] = in->container;
- soid_eids[1] = in->object;
- soid_eids[2] = REP_FACTOR_FORK;
-
- ret = sos_read(&soid, 0, 1, 0, 0, &ondisk_rep_factor, sizeof(ondisk_rep_factor), &ribuf, 1, grp, &nbytes, &nrec_infos, &update_info, &sos_rc);
+ ret = hoss_read(&soid, 0, 1, 0, 0, &ondisk_rep_factor, sizeof(ondisk_rep_factor), &ribuf, 1, grp, &nbytes, &nrec_infos, &update_info, &hoss_rc);
- if(ret == 0 && sos_rc == 0 && nbytes == sizeof(ondisk_rep_factor))
+ if(ret == 0 && hoss_rc == 0 && nbytes == sizeof(ondisk_rep_factor))
{
triton_debug(triton_dbg_rosd, "rosd_write() found on-disk replication factor of %d\n", ondisk_rep_factor);
@@ -311,8 +312,8 @@ static __blocking triton_ret_t resolve_replication_factor(
/* caller requested a replication factor that doesn't match
* current replication for this object.
*/
- triton_error_msg("sos_read() failure for replication factor\n");
- sos_end(grp, 0);
+ triton_error_msg("hoss_read() failure for replication factor\n");
+ hoss_end(grp, 0);
return(TRITON_ERR_IO);
}
}
@@ -338,16 +339,16 @@ static __blocking triton_ret_t resolve_replication_factor(
triton_debug(triton_dbg_rosd, "rosd_write() writing on-disk replication factor of %d\n", ondisk_rep_factor);
/* write new replication factor to disk */
- ret = sos_write(&soid, 0, 1, sizeof(ondisk_rep_factor), 0, 0, 0, &ondisk_rep_factor, grp, &nbytes, &sos_rc);
- if(ret != 0 || sos_rc != 0 || nbytes != sizeof(ondisk_rep_factor))
+ ret = hoss_write(&soid, 0, 1, sizeof(ondisk_rep_factor), 0, 0, 0, &ondisk_rep_factor, grp, &nbytes, &hoss_rc);
+ if(ret != 0 || hoss_rc != 0 || nbytes != sizeof(ondisk_rep_factor))
{
- triton_error_msg("sos_write() failure for replication factor, return code %d\n", ret);
- sos_end(grp, 0);
+ triton_error_msg("hoss_write() failure for replication factor, return code %d\n", ret);
+ hoss_end(grp, 0);
return(TRITON_ERR_IO);
}
}
- ret = sos_end(grp, 1);
+ ret = hoss_end(grp, 1);
if(ret != 0)
{
return(TRITON_ERR_IO);
@@ -432,9 +433,9 @@ static __blocking triton_ret_t triton_rpc_rosd_write(hg_handle_t handle)
/* now check that the replication factor is valid and store it on disk
* if needed
- * NOTE: wrapped in a loop to handle sos txn retries
+ * NOTE: wrapped in a loop to handle hoss txn retries
*/
- /* TODO: fix error codes; need to differentiate sos canceled (which
+ /* TODO: fix error codes; need to differentiate hoss canceled (which
* means we should retry) from aesop canceled (which means the operation
* has been explicitly canceled by another thread, likely due to error
* cleanup)
@@ -451,7 +452,7 @@ static __blocking triton_ret_t triton_rpc_rosd_write(hg_handle_t handle)
* again
*/
free(addr_array);
- addr_array = malloc(test_rep_factor*sizeof(*addr_array));
+ addr_array = malloc(in.replication_factor*sizeof(*addr_array));
if(!addr_array)
{
out.tret = TRITON_ERR_NOMEM;
@@ -459,7 +460,8 @@ static __blocking triton_ret_t triton_rpc_rosd_write(hg_handle_t handle)
return(TRITON_SUCCESS);
}
- out.tret = triton_oid_to_addrs(in.object, test_rep_factor, &my_position, addr_array);
+ out.tret = triton_oid_to_addrs(in.object, in.replication_factor,
+ &my_position, addr_array);
if(triton_is_error(out.tret))
{
triton_mercury_respond(handle, &out);
@@ -471,7 +473,7 @@ static __blocking triton_ret_t triton_rpc_rosd_write(hg_handle_t handle)
/* TODO: check flags to make sure this isn't an explicit conditional */
/* TODO: revise txn_nr_cache to query correct version number out of
- * SOS; for now we just hard code version number to 0.
+ * hoss; for now we just hard code version number to 0.
*/
#if 0
if(in.expected_position == 0)
@@ -611,7 +613,7 @@ static __blocking triton_ret_t rosd_write_do_work(
{
triton_debug(triton_dbg_rosd, "ROSD local write of oid %llu on %d'th server, update_id %llu.\n", llu(in->object), my_position, llu(in->update_id_condition));
/* perform local operation */
- /* TODO: fix error codes; need to differentiate sos canceled (which
+ /* TODO: fix error codes; need to differentiate hoss canceled (which
* means we should retry) from aesop canceled (which means the operation
* has been explicitly canceled by another thread, likely due to error
* cleanup)
@@ -680,17 +682,17 @@ static __blocking triton_ret_t rosd_write_local_storage(
uint64_t update_id_condition,
uint64_t *new_update_id)
{
- struct sos_grp *grp;
- struct sos_oid soid;
- sos_eid_t soid_eids[3];
- sos_size_t nbytes;
- sos_update_t update_info;
- int ret, sos_rc;
-
- /* TODO: handle canceled error code (or whatever sos will report to
+ struct hoss_grp *grp;
+ struct hoss_oid soid;
+ hoss_eid_t soid_eids[3];
+ hoss_size_t nbytes;
+ hoss_update_t update_info;
+ int ret, hoss_rc;
+
+ /* TODO: handle canceled error code (or whatever hoss will report to
* indicate that a txn failed and should be retried)
*/
- ret = sos_begin(&grp, NULL, 0, g_sos_ctx);
+ ret = hoss_begin(&grp, NULL, 0, g_hoss_ctx);
if(ret != 0)
{
return(TRITON_ERR_IO);
@@ -703,15 +705,15 @@ static __blocking triton_ret_t rosd_write_local_storage(
soid_eids[2] = fork;
/* TODO: the update id arguments probably aren't right here... */
- ret = sos_write(&soid, start_record, recordcount, recordlen, 0, 0, update_id_condition, buffer, grp, &nbytes, &sos_rc);
- if(ret != 0 || sos_rc != 0 || nbytes != recordcount*recordlen)
+ ret = hoss_write(&soid, start_record, recordcount, recordlen, 0, 0, update_id_condition, buffer, grp, &nbytes, &hoss_rc);
+ if(ret != 0 || hoss_rc != 0 || nbytes != recordcount*recordlen)
{
- triton_error_msg("sos_write() failure, return code %d\n", ret);
- sos_end(grp, 0);
+ triton_error_msg("hoss_write() failure, return code %d\n", ret);
+ hoss_end(grp, 0);
return(TRITON_ERR_IO);
}
- ret = sos_end(grp, 1);
+ ret = hoss_end(grp, 1);
if(ret != 0)
{
return(TRITON_ERR_IO);
diff --git a/code/src/replicated-osd/rosd.ae b/code/src/replicated-osd/rosd.ae
index 0894c3d..4162dd2 100644
--- a/code/src/replicated-osd/rosd.ae
+++ b/code/src/replicated-osd/rosd.ae
@@ -31,7 +31,7 @@ int64_t rosd_write_buffer_size = -1;
uint32_t rosd_default_replication_factor = -1;
int64_t rosd_read_xfer_pipeline_depth = -1;
int64_t rosd_write_xfer_pipeline_depth = -1;
-struct sos_ctx *g_sos_ctx;
+struct hoss_ctx *g_hoss_ctx;
struct buffer_mgmt_instance* rosd_read_buffers = NULL;
struct buffer_mgmt_instance* rosd_write_buffers = NULL;
@@ -66,7 +66,7 @@ static triton_ret_t rosd_param_updater(const char* key, const char *value)
return(tret);
}
-triton_ret_t triton_rosd_svr_init(struct sos_ctx *sos_ctx)
+triton_ret_t triton_rosd_svr_init(struct hoss_ctx *hoss_ctx)
{
triton_ret_t tret = TRITON_SUCCESS;
int ret;
@@ -75,7 +75,7 @@ triton_ret_t triton_rosd_svr_init(struct sos_ctx *sos_ctx)
if(!module_refcount)
{
- g_sos_ctx = sos_ctx;
+ g_hoss_ctx = hoss_ctx;
triton_zeroconf_register_callback(
"triton_rosd_default_replication_factor", rosd_param_updater);
@@ -212,7 +212,6 @@ triton_ret_t triton_oid_to_addrs(
return(tret);
}
-
oid_l = triton_uint128_from_uint64(oid);
oid_str = triton_uint128_to_string(oid_l);
diff --git a/code/src/replicated-osd/rosd.hae b/code/src/replicated-osd/rosd.hae
index d044513..649468b 100644
--- a/code/src/replicated-osd/rosd.hae
+++ b/code/src/replicated-osd/rosd.hae
@@ -4,7 +4,7 @@
#include <aesop/aesop.h>
#include <aesop/sem.hae>
#include <mercury.h>
-#include <sos.hae>
+#include <hoss.hae>
#include "src/common/triton-error.h"
#include "src/replicated-osd/buffer-mgmt.hae"
@@ -35,7 +35,7 @@ struct rosd_record_info{
uint64_t record_update_id; /* version of each record in sequence */
};
-triton_ret_t triton_rosd_svr_init(struct sos_ctx *sos_ctx);
+triton_ret_t triton_rosd_svr_init(struct hoss_ctx *hoss_ctx);
void triton_rosd_svr_finalize(void);
diff --git a/code/src/server/triton-server.ae b/code/src/server/triton-server.ae
index 3f133f3..1653d91 100644
--- a/code/src/server/triton-server.ae
+++ b/code/src/server/triton-server.ae
@@ -9,7 +9,7 @@
#include <getopt.h>
#include <aesop/aesop.h>
-#include <sos.hae>
+#include <hoss.hae>
#include "src/remote/mercury-engine.hae"
#include "src/common/resources/signal/signal.hae"
#include "src/common/triton-debug.h"
@@ -19,6 +19,7 @@
#include "src/system-state/system-state-engine.hae"
#include "src/replicated-osd/rosd.hae"
#include "src/placement/placement.h"
+#include "src/zeroconf/zeroconf.h"
static triton_ret_t make_daemon(void);
@@ -106,10 +107,10 @@ __blocking int aesop_main(int argc, char **argv)
triton_ret_t tret;
char* listen_addr;
char* conffile;
- const char * sos_path;
+ const char * hoss_path;
char logname[PATH_MAX];
int daemonize;
- struct sos_ctx *sos_ctx;
+ struct hoss_ctx *hoss_ctx;
int ret;
parse_args(&argc,
@@ -187,19 +188,19 @@ __blocking int aesop_main(int argc, char **argv)
*/
/* TODO: better encapsulate this */
- sos_path = triton_zeroconf_get("triton_sos_base_path");
- if (sos_path == NULL){
- triton_error_msg("config variable triton_sos_base_path "
+ hoss_path = triton_zeroconf_get("triton_hoss_base_path");
+ if (hoss_path == NULL){
+ triton_error_msg("config variable triton_hoss_base_path "
"not present, exiting...\n");
/* tosd_finalize(); */
triton_place_finalize();
triton_debug_finalize();
return(-1);
}
- ret = sos_init(&sos_ctx, sos_path);
+ ret = hoss_init(&hoss_ctx, hoss_path);
if(ret != 0)
{
- triton_error_msg_ret(tret, "sos_init()");
+ triton_error_msg_ret(tret, "hoss_init()");
/*tosd_finalize();*/
triton_place_finalize();
triton_debug_finalize();
@@ -218,7 +219,7 @@ __blocking int aesop_main(int argc, char **argv)
{
triton_error_msg_ret(tret, "triton_signal_init()");
triton_error_destroy(tret);
- sos_fini(sos_ctx);
+ hoss_fini(hoss_ctx);
tosd_finalize();
triton_place_finalize();
triton_debug_finalize();
@@ -229,12 +230,12 @@ __blocking int aesop_main(int argc, char **argv)
#endif
/* intialize rosd */
- tret = triton_rosd_svr_init(sos_ctx);
+ tret = triton_rosd_svr_init(hoss_ctx);
if(triton_is_error(tret))
{
triton_error_msg_ret(tret, "triton_rosd_svr_init()");
triton_error_destroy(tret);
- sos_fini(sos_ctx);
+ hoss_fini(hoss_ctx);
/*tosd_finalize();*/
triton_place_finalize();
triton_debug_finalize();
@@ -252,7 +253,7 @@ __blocking int aesop_main(int argc, char **argv)
triton_error_msg_ret(tret, "triton_mercury_engine_init()");
triton_error_destroy(tret);
triton_rosd_svr_finalize();
- sos_fini(sos_ctx);
+ hoss_fini(hoss_ctx);
/*tosd_finalize();*/
#if 0
triton_signal_finalize();
@@ -270,7 +271,7 @@ __blocking int aesop_main(int argc, char **argv)
triton_error_destroy(tret);
triton_mercury_engine_finalize();
triton_rosd_svr_finalize();
- sos_fini(sos_ctx);
+ hoss_fini(hoss_ctx);
/*tosd_finalize();*/
#if 0
triton_signal_finalize();
@@ -342,7 +343,7 @@ __blocking int aesop_main(int argc, char **argv)
triton_info_msg("Server shutting down cleanly\n");
triton_rosd_svr_finalize();
- sos_fini(sos_ctx);
+ hoss_fini(hoss_ctx);
/*tosd_finalize();*/
triton_core_rpc_finalize();
triton_mercury_engine_finalize();
diff --git a/code/src/zeroconf/zeroconf.c b/code/src/zeroconf/zeroconf.c
index 339aa61..8022b32 100644
--- a/code/src/zeroconf/zeroconf.c
+++ b/code/src/zeroconf/zeroconf.c
@@ -40,10 +40,10 @@ struct zeroconf_entry zeroconf_array[] =
"Debug mask to enable debugging of various triton components",
NULL,
},
- /* sos configuration parameters (TODO: grow) */
+ /* hoss configuration parameters (TODO: grow) */
{
- CFG_STR("triton_sos_base_path", 0, CFGF_NONE),
- "SOS data/metadata path",
+ CFG_STR("triton_hoss_base_path", 0, CFGF_NONE),
+ "HOSS data/metadata path",
NULL
},
/* object placement */
hooks/post-receive
--
1
0
branch, trac-323-sos, updated. 071f493b20f6ea57abd54d78da037573f4b53acb
by noreply@mcs.anl.gov 22 Jan '15
by noreply@mcs.anl.gov 22 Jan '15
22 Jan '15
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, trac-323-sos has been updated
via 071f493b20f6ea57abd54d78da037573f4b53acb (commit)
from 65dd7d7fa627b6f92450875953344a0c560d626c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 071f493b20f6ea57abd54d78da037573f4b53acb
Author: John Jenkins <jenkins(a)mcs.anl.gov>
Date: Thu Jan 22 13:57:53 2015 -0600
update sos-read/write calls
brings triton back to compilability, but not testability :)
-----------------------------------------------------------------------
Summary of changes:
code/src/replicated-osd/rosd-write.ae | 19 ++++++++++---------
1 files changed, 10 insertions(+), 9 deletions(-)
Diff of changes:
diff --git a/code/src/replicated-osd/rosd-write.ae b/code/src/replicated-osd/rosd-write.ae
index 883b5d5..c5b4c31 100644
--- a/code/src/replicated-osd/rosd-write.ae
+++ b/code/src/replicated-osd/rosd-write.ae
@@ -270,9 +270,10 @@ static __blocking triton_ret_t resolve_replication_factor(
struct sos_oid soid;
sos_eid_t soid_eids[3];
int32_t ondisk_rep_factor;
- sos_size_t nbytes;
+ sos_size_t nbytes, nrec_infos;
sos_update_t update_info;
- int ret;
+ struct sos_record_info ribuf;
+ int ret, sos_rc;
/* TODO: check for "CANCELED" return code from sos once supported. In
* that case we need to kick out of this function so that it can be
@@ -297,9 +298,9 @@ static __blocking triton_ret_t resolve_replication_factor(
soid_eids[1] = in->object;
soid_eids[2] = REP_FACTOR_FORK;
- ret = sos_read(&soid, 0, 1, 0, 0, &ondisk_rep_factor, sizeof(ondisk_rep_factor), &nbytes, &update_info, grp);
+ ret = sos_read(&soid, 0, 1, 0, 0, &ondisk_rep_factor, sizeof(ondisk_rep_factor), &ribuf, 1, grp, &nbytes, &nrec_infos, &update_info, &sos_rc);
- if(ret == 0 && nbytes == sizeof(ondisk_rep_factor))
+ if(ret == 0 && sos_rc == 0 && nbytes == sizeof(ondisk_rep_factor))
{
triton_debug(triton_dbg_rosd, "rosd_write() found on-disk replication factor of %d\n", ondisk_rep_factor);
@@ -337,8 +338,8 @@ static __blocking triton_ret_t resolve_replication_factor(
triton_debug(triton_dbg_rosd, "rosd_write() writing on-disk replication factor of %d\n", ondisk_rep_factor);
/* write new replication factor to disk */
- ret = sos_write(&soid, 0, 1, sizeof(ondisk_rep_factor), 0, 0, 1, &ondisk_rep_factor, &nbytes, grp);
- if(ret != 0 || nbytes != sizeof(ondisk_rep_factor))
+ ret = sos_write(&soid, 0, 1, sizeof(ondisk_rep_factor), 0, 0, 0, &ondisk_rep_factor, grp, &nbytes, &sos_rc);
+ if(ret != 0 || sos_rc != 0 || nbytes != sizeof(ondisk_rep_factor))
{
triton_error_msg("sos_write() failure for replication factor, return code %d\n", ret);
sos_end(grp, 0);
@@ -684,7 +685,7 @@ static __blocking triton_ret_t rosd_write_local_storage(
sos_eid_t soid_eids[3];
sos_size_t nbytes;
sos_update_t update_info;
- int ret;
+ int ret, sos_rc;
/* TODO: handle canceled error code (or whatever sos will report to
* indicate that a txn failed and should be retried)
@@ -702,8 +703,8 @@ static __blocking triton_ret_t rosd_write_local_storage(
soid_eids[2] = fork;
/* TODO: the update id arguments probably aren't right here... */
- ret = sos_write(&soid, start_record, recordcount, recordlen, 0, 0, update_id_condition, buffer, &nbytes, grp);
- if(ret != 0 || nbytes != recordcount*recordlen)
+ ret = sos_write(&soid, start_record, recordcount, recordlen, 0, 0, update_id_condition, buffer, grp, &nbytes, &sos_rc);
+ if(ret != 0 || sos_rc != 0 || nbytes != recordcount*recordlen)
{
triton_error_msg("sos_write() failure, return code %d\n", ret);
sos_end(grp, 0);
hooks/post-receive
--
1
0
branch, trac-323-sos, updated. 65dd7d7fa627b6f92450875953344a0c560d626c
by noreply@mcs.anl.gov 22 Jan '15
by noreply@mcs.anl.gov 22 Jan '15
22 Jan '15
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, trac-323-sos has been updated
via 65dd7d7fa627b6f92450875953344a0c560d626c (commit)
via 9c9d7b4da56fbac8bd3b1258198026ec6d0d91e2 (commit)
via cdf42d8449873a456fd06e7ee2e3f364b1db317b (commit)
via ba94250fcc2c3422624fc4b1333f8da9a2575fb9 (commit)
via 70e737adccf462bc31b56026e98d45ebbd9b583a (commit)
via c6ddcf62401074ae562fb7cd0565e193de0ebc4b (commit)
via 620c087a59b742cab81bac45eb14621cafe1a6ce (commit)
via 584ca9b14992a628cf0357e5f7ce4ab968ff4af6 (commit)
via 98ec02463406f5d86b5fa866e30f708855389074 (commit)
via f297517d8c2e25a936bf44ebb43ddb5b9c408bbe (commit)
via fca67ed039f6e74ff450cca2ac1d96861ba4b52a (commit)
via f86a7f8e49fad3b5160604691a48582539a55976 (commit)
via a9252091c59fbd80d838dbe4722b3863c1a22b83 (commit)
via 29661aa8ce90ede1bc67a3cf28a03433c3a67b5d (commit)
via b24c3dcd9640d168f32c1c830cc74891ae99478d (commit)
from d5ffc57b8ffdbf92760b4e8d0630b9795ceecddf (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 65dd7d7fa627b6f92450875953344a0c560d626c
Merge: d5ffc57b8ffdbf92760b4e8d0630b9795ceecddf 9c9d7b4da56fbac8bd3b1258198026ec6d0d91e2
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Thu Jan 22 10:55:42 2015 -0500
Merge remote-tracking branch 'origin/master' into trac-323-sos
Conflicts:
code/include/asg.h
code/src/remote/mercury-engine.hae
code/src/replicated-osd/rosd-read.ae
code/src/replicated-osd/rosd-write.ae
code/tests/Makefile.subdir
NOTE: untested
-----------------------------------------------------------------------
Summary of changes:
code/Make.rules | 8 +-
code/include/Doxyfile | 2352 ++++++++++++++++++++
code/include/asg.h | 531 ++++-
code/maint/depend-ae.sh | 2 +-
.../tosd/transactional-osd/transactional-osd.ae | 18 +
code/scripts/jenkins/repos.fetch | 2 +-
code/src/admin-tools/triton-show-config.ae | 11 -
code/src/remote/core-rpc.ae | 110 +-
code/src/remote/mercury-engine.ae | 2 +
code/src/remote/mercury-engine.hae | 31 +-
code/src/remote/mercury-rsc.c | 3 +-
code/src/replicated-osd/rosd-alloc.ae | 2 +-
code/src/replicated-osd/rosd-read.ae | 2 +-
code/src/replicated-osd/rosd-write.ae | 2 +-
code/src/system-state/system-state.ae | 112 +-
code/tests/Makefile.subdir | 7 +-
code/tests/asg/test-asg-multi-init.c | 50 +
.../{test-asg-simple.sh => test-asg-multi-init.sh} | 2 +-
misc/experiments/ior-asg/README | 5 +-
.../example_input/ior_asg.conf.many.template | 18 +
.../ior-asg/example_input/ior_asg.conf.template | 4 +-
misc/experiments/ior-asg/ior-run.sh | 189 ++-
misc/experiments/ior-asg/run-tukey-example.sh | 12 +-
23 files changed, 3241 insertions(+), 234 deletions(-)
create mode 100644 code/include/Doxyfile
create mode 100644 code/tests/asg/test-asg-multi-init.c
copy code/tests/asg/{test-asg-simple.sh => test-asg-multi-init.sh} (91%)
create mode 100644 misc/experiments/ior-asg/example_input/ior_asg.conf.many.template
Diff of changes:
diff --git a/code/Make.rules b/code/Make.rules
index c20bca5..bc9c96c 100644
--- a/code/Make.rules
+++ b/code/Make.rules
@@ -15,10 +15,10 @@ tests: $(check_PROGRAMS)
# rule for compiling aesop .ae files
#
.ae.o:
- $(AM_V_GEN)$(AECC) -o $@ $< -- $(CFLAGS)
+ $(AM_V_GEN)$(AECC) -o $@ $< -- $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $(AM_CFLAGS)
.hae.h:
- $(AM_V_GEN)$(AECC) -o $@ $< -j -- $(CFLAGS)
+ $(AM_V_GEN)$(AECC) -o $@ $< -j -- $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $(AM_CFLAGS)
#
# rules for .ae dependencies
@@ -27,11 +27,11 @@ dirname = $(patsubst %/,%,$(dir $(1)))
%.ae.d: %.ae
mkdir -p $(call dirname,$@)
- $(AM_V_GEN)CC="$(CC)" CFLAGS="$(CFLAGS)" $(srcdir)/maint/depend-ae.sh $(call dirname,$@) $< > $@
+ $(AM_V_GEN)CC="$(CC)" CPPFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS)" CFLAGS="$(AM_CFLAGS) $(CFLAGS)" $(srcdir)/maint/depend-ae.sh $(call dirname,$@) $< > $@
%.hae.d: %.hae
mkdir -p $(call dirname,$@)
- $(AM_V_GEN)CC="$(CC)" CFLAGS="$(CFLAGS)" $(srcdir)/maint/depend-ae.sh $(call dirname,$@) $< > $@
+ $(AM_V_GEN)CC="$(CC)" CPPFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS)" CFLAGS="$(AM_CFLAGS) $(CFLAGS)" $(srcdir)/maint/depend-ae.sh $(call dirname,$@) $< > $@
#============================================================================
# Asciidoc rules
diff --git a/code/include/Doxyfile b/code/include/Doxyfile
new file mode 100644
index 0000000..a79827f
--- /dev/null
+++ b/code/include/Doxyfile
@@ -0,0 +1,2352 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "ASG"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = NO
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = NO
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT =
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html) You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/) introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace)
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes)
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/)
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/) See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/) a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: YES.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/code/include/asg.h b/code/include/asg.h
index b4d8868..5c9105b 100644
--- a/code/include/asg.h
+++ b/code/include/asg.h
@@ -1,9 +1,22 @@
-/* Revised following meeting on March 17, 2014 to accommodate the following
- * proposed changes:
+/** \defgroup ASG ASG object interface
+ *
+ * Client-side API providing access to a distributed object
+ * storage system. It presents a hierarchy consisting of containers,
+ * objects, forks, and records in which data can be stored.
*
+ * Revised following meeting on March 17, 2014 to accommodate the following
+ * proposed changes:
* - switch from "version" to "update id" terminology
* - add probe parameters to asg_read call to support read+probe semantics
* in a single API operation
+ * .
+ * current API level is 1.1.0
+ *
+ * @{
+ */
+
+/** \file
+ * Declarations for the ASG object storage API.
*/
#ifndef TRITON_ASG_H
@@ -17,44 +30,121 @@ extern "C"
{
#endif
-/* current API level is 1.1.0 */
-/* update ASG_VERSION_MAJOR on major feature or semantic changes */
+/** Major version number of API
+ * @note update on major feature or semantic changes
+ */
#define ASG_VERSION_MAJOR 1
-/* update ASG_VERSION_MINOR on minor changes that break API compatibility */
+
+/** Minor version number of API
+ * @note update on minor changes that break API compatibility
+ */
#define ASG_VERSION_MINOR 1
-/* update ASG_VERSION_SUB on minor changes that do not break API
- * compatibility */
+
+/** Sub version number of API
+ * @note update on do not break API compatibility
+ */
#define ASG_VERSION_SUB 0
+/** An instantiation of the ASG interface */
typedef intptr_t asg_instance_t;
+/** A storage location (e.g. a remote server)
+ * @note not all implementations will allow the location to be explicitly
+ * specified; @see ASG_LOCATION_AUTO
+ */
typedef intptr_t asg_location_t;
-typedef uint64_t asg_container_id_t;
-typedef uint64_t asg_object_id_t;
-typedef uint64_t asg_fork_id_t;
+/** A record identifier.
+ *
+ * A record is the basic storage block for the storage system. A record
+ * consists out of a numeric key or record id, a number indicating
+ * the update ID (roughly analogous to a record-granular version number),
+ * the record’s data, and the length of record’s data. The data is a
+ * variable length array of bytes. Empty records (i.e. records for which
+ * the data has length 0) are allowed.
+ */
typedef uint64_t asg_record_id_t;
+/** A fork identifier.
+ *
+ * Each fork within an object has a fork id: a fixed length integer number.
+ * A fork contains zero or more records, and forms a distinct
+ * key space for the records it contains.
+ */
+typedef uint64_t asg_fork_id_t;
+
+/** An object identifier.
+ *
+ * An object is a collection of forks. Objects form a unique name space for
+ * the enclosed forks, i.e. the same fork id within a different
+ * object represents a different fork.
+ */
+typedef uint64_t asg_object_id_t;
+
+/**
+ * A container identifier.
+ *
+ * A container consists out of a collection of objects. Each container forms
+ * a unique name space for the objects it encloses.
+ * Containers can be used to partition the storage system into logical
+ * units. For example, each container could hold its own file
+ * system. Containers provide isolation.
+ * Containers cannot be nested.
+ */
+typedef uint64_t asg_container_id_t;
+
+/**
+ * @todo asg_offset_t seems to be unused, can we delete it?
+ */
typedef uint64_t asg_offset_t;
-typedef uint64_t asg_size_t;
+/**
+ * Size type, used to indicate the size of records, buffers, etc.
+ */
+typedef uint64_t asg_size_t;
+/**
+ * Indicates the update identifier for a particular record. This is
+ * somewhat like a record-granular version number. Higher update id values
+ * deprecate lower update id values, and only the highest update id value
+ * for a given record is readable.
+ *
+ * Update IDs can be used to perform atomic conditional operations on records,
+ * compare records for replica consistency, or to resolve overlapping
+ * operations in a consistent manner.
+ */
typedef uint64_t asg_update_id_t;
/** The highest valid update_id number */
#define ASG_UPDATE_ID_MAX (UINT64_MAX-1)
-/** Constant indicating multiple update_ids
- * (used in reading) */
+/** Special value update_id value used (at read time) indicate that a set of
+ * records have a mixture of different update ID values.
+ */
#define ASG_UPDATE_ID_MIXED UINT64_MAX
-
+/** Special value for asg_location_t; indicates that the caller does not
+ * wish to specify the storage location for the object. The storage system
+ * is free to choose the location.
+ */
#define ASG_LOCATION_AUTO 0
+/** Special value for asg_record_id_t to indicate a null or unspecified
+ * record.
+ */
#define ASG_RECORD_NULL 0
+/** Special value for asg_fork_id_t to indicate a null or unspecified
+ * record.
+ */
#define ASG_FORK_NULL 0
+/** Special value for asg_object_id_t to indicate a null or unspecified
+ * record.
+ */
#define ASG_OBJECT_NULL 0
+/** Special value for asg_object_id_t to indicate a null or unspecified
+ * container.
+ */
#define ASG_CONTAINER_NULL 0
/**
@@ -62,16 +152,21 @@ typedef uint64_t asg_update_id_t;
*/
typedef enum
{
- ASG_SUCCESS = 0,
- ASG_ERR_UPDATE_ID = 1,
- ASG_ERR_LOCATION = 2,
- ASG_ERR_OTHER = 666
+ ASG_SUCCESS = 0, /**< operation succeeded */
+ ASG_ERR_UPDATE_ID = 1, /**< operation failed due to conditional test */
+ ASG_ERR_LOCATION = 2, /**< operation failed due to invalid location */
+ ASG_ERR_OTHER = 666 /**< all other failure modes */
} asg_ret_t;
/**
- * Flags for use in read,write,punch.
+ * Flags that modify the behavior of read, write, and punch.
+ *
+ * @note the ASG_COND* flags work in conjunction with the
+ * update_id_condition argument of each function to impliment conditional
+ * operations: operations that will atomically fail or succeed based on a
+ * comparison of update ID values.
*/
typedef enum
{
@@ -98,51 +193,184 @@ typedef enum
* existing update_id numbers in the range. */
ASG_AUTO_UPDATE_ID = 0x0004,
+ /** @todo What does this flag do?
+ */
ASG_WRITE_FIXED_DATA = 0x0008,
} asg_flags_t;
+/** Describes 1 or more records that have contiguous record ID values and
+ * identical lengths.
+ */
typedef struct
{
- asg_record_id_t record_id; /** number of first record in the sequence */
- asg_size_t seq_len; /** Number of records in sequence */
- asg_size_t record_len; /** Length of each record in sequence */
- asg_update_id_t record_update_id; /** Version of each record in seq */
+ asg_record_id_t record_id; /**< ID of first record in the sequence */
+ asg_size_t seq_len; /**< number of records in sequence */
+ asg_size_t record_len; /**< Length of each record in sequence */
+ asg_update_id_t record_update_id; /**< update_id of each record in seq */
} asg_record_info_t;
+/**
+ * Describes 1 or more containers that have contiguous container ID values
+ * and identical object counts.
+ *
+ * @note It seems unlikely that a sequence of containers will all have the
+ * same value for object_count. This capability of describing a sequence of
+ * containers with a single container_info_t is mainly here to be consistent
+ * with the record_info_t struct.
+ */
+typedef struct
+{
+ asg_container_id_t container_id; /**< ID of first container in the sequence */
+ asg_size_t seq_len; /**< Number of containers in sequence */
+ asg_size_t object_count; /**< Number of objects within each container */
+} asg_container_info_t;
+
+/**
+ * Describes 1 or more objects that have contiguous object ID values and
+ * identical fork counts.
+ */
+typedef struct
+{
+ asg_container_id_t object_id; /**< ID of first object in the sequence */
+ asg_size_t seq_len; /**< Number of objects in sequence */
+ asg_size_t fork_count; /**< Number of forks within each object */
+} asg_object_info_t;
+
+/**
+ * Describes 1 or more forks that have contigous fork ID values and
+ * identical record counts.
+ */
+typedef struct
+{
+ asg_fork_id_t fork_id; /**< ID of first fork in the sequence */
+ asg_size_t seq_len; /**< Number of forks in sequence */
+ asg_size_t record_count; /**< Number of records within each fork */
+} asg_fork_info_t;
+
/* ========================================================================*/
-/** Initialize storage system instance */
-int asg_initialize (asg_instance_t * instance, const char * options);
+/**
+ * Initialize storage system instance. Must be called before any other ASG
+ * interface functions.
+ *
+ * @param[out] instance Interface instance
+ * @param[in] options Configuration options in string format
+ */
+int asg_initialize (
+ asg_instance_t * instance,
+ const char * options
+);
-/** Close storage system instance */
-int asg_finalize (asg_instance_t instance);
+/**
+ * Close storage system instance. Should be called only after all ASG
+ * interface operations are complete.
+ *
+ * @param[in] instance Interface instance to be shut down
+ */
+int asg_finalize (
+ asg_instance_t instance
+);
/**
- * Retrieve data
- * - The update_id number of the region is returned in update_id_info:
- * either a specific update_id number, or -- if multiple update_ids
- * are present in the range -- ASG_UPDATE_ID_MIXED
+ * Retrieve data from one or more contiguous records in a fork. The records
+ * need not be the same size or update ID number, but they must be contiguous
+ * in terms of their record IDs.
+ *
+ * @param[in] instance Interface instance
+ * @param[in] location Storage system location
+ * @param[in] container
+ * @param[in] object
+ * @param[in] fork
+ * @param[in] start_record First record in the contigous sequence to be read
+ * @param[in] recordcount Number of records to read
+ * @param[in] flags Flags to modify behavior or specify conditional modes
+ * @param[in] update_id_condition Update ID value to use for comparison
+ * tests in conditional mode
+ * @param[out] buf Data payload read from disk. May contain data from
+ * multiple records serialized into a single byte stream.
+ * @param[in] bufsize Size of buf memory provided by caller (bytes)
+ * @param[out] transferred Number of bytes read into buf
+ * @param[out] record_buf Array describing records read from storage system.
+ * @param[in,out] record_buf_transferred Number of record_buf elements
+ * provided by the caller on input, and the number of record_buf elements
+ * actually filled in by the ASG API on output.
+ * @param[out] update_id_info indicates the update ID value of the records
+ * that were read from the storage system. Will be set to
+ * ASG_UPDATE_ID_MIXED if multiple records were read and they do not all
+ * share the same record ID.
*
- * */
+ * @todo Change name of record_buf_transferred parameter if it is really an
+ * in,out parameter and not just output?
+ * @todo The update_id_info parameter seems redundant: this same information
+ * is also present in the record_buf argument.
+ * @todo Document the failure modes. What if the records (or some of them)
+ * don't exist? What if bufsize or record_buf_transferred is not large
+ * enough to hold the payload or record descriptions?
+ * @todo Which (if any) out arguments can be set to NULL if you don't care to
+ * have them filled in? Possibilities include udpate_id_info,
+ * record_buf_transferred, and record_buf.
+ */
int asg_read (
- asg_instance_t instance,
- asg_location_t location,
- asg_container_id_t container,
- asg_object_id_t object,
- asg_fork_id_t fork,
- asg_record_id_t start_record,
- asg_size_t recordcount,
- asg_flags_t flags,
- asg_update_id_t update_id_condition,
- void * buf,
- size_t bufsize,
- asg_size_t * transferred,
- asg_record_info_t * record_buf,
- asg_size_t * record_buf_transferred,
- asg_update_id_t * update_id_info);
+ asg_instance_t instance,
+ asg_location_t location,
+ asg_container_id_t container,
+ asg_object_id_t object,
+ asg_fork_id_t fork,
+ asg_record_id_t start_record,
+ asg_size_t recordcount,
+ asg_flags_t flags,
+ asg_update_id_t update_id_condition,
+ void * buf,
+ size_t bufsize,
+ asg_size_t * transferred,
+ asg_record_info_t * record_buf,
+ asg_size_t * record_buf_transferred,
+ asg_update_id_t * update_id_info);
+/**
+ * Write data to one or more contiguous records in a fork. The records
+ * @e must all be the same size and update ID number.
+ *
+ * @param[in] instance Interface instance
+ * @param[in] location Storage system location
+ * @param[in] container
+ * @param[in] object
+ * @param[in] fork
+ * @param[in] start_record First record in the contigous sequence to be
+ * written
+ * @param[in] recordcount Number of records to be written
+ * @param[in] recordlen Size of each record to be written
+ * @param[in] flags Flags to modify behavior or specify conditional modes
+ * @param[in] update_id_condition Update ID value to use for comparison
+ * tests in conditional mode
+ * @param[out] new_update_id Update ID value stored on disk; this is only
+ * filled in when using ASG_AUTO_UPDATE_ID flag.
+ * @param[out] data Data payload to be written. May contain data from
+ * multiple records serialized into a single byte stream. The size of the
+ * data buffer in bytes must be recordcount*recordlen.
+ * @param[out] transferred The number of records written (in case of short
+ * write, as in ASG_COND_UNTIL)
+ * @param[in] bufsize Size of buf memory provided by caller (bytes)
+ * @param[out] transferred Number of bytes read into buf
+ * @param[out] record_buf Array describing records read from storage system.
+ * @param[in,out] record_buf_transferred Number of record_buf elements
+ * provided by the caller on input, and the number of record_buf elements
+ * actually filled in by the ASG API on output.
+ * @param[out] update_id_info indicates the update ID value of the records
+ * that were read from the storage system. Will be set to
+ * ASG_UPDATE_ID_MIXED if multiple records were read and they do not all
+ * share the same record ID.
+ *
+ * @todo Why is the data payload argument called "buf" in the read function
+ * but "data" in the write function?
+ * @todo Confirm the units of the "transferred" argument and then adjust
+ * name accordingly for clarity. Here I assume that it is the number of
+ * records successfully written, in which case "records_transferred" would
+ * be a more helpful name.
+ *
+ */
int asg_write (
asg_instance_t instance,
asg_location_t location,
@@ -161,7 +389,26 @@ int asg_write (
/**
* Punch is exactly like write but writes zero length records.
*
- * Transferred indicates the number of records updated.
+ * @param[in] instance Interface instance
+ * @param[in] location Storage system location
+ * @param[in] container
+ * @param[in] object
+ * @param[in] fork
+ * @param[in] start_record First record in the contigous sequence to be
+ * punched
+ * @param[in] recordcount Number of records to be punched
+ * @param[in] flags Flags to modify behavior or specify conditional modes
+ * @param[in] update_id_condition Update ID value to use for comparison
+ * tests in conditional mode
+ * @param[out] new_update_id Update ID value stored on disk; this is only
+ * filled in when using ASG_AUTO_UPDATE_ID flag.
+ * @param[out] transferred The number of records punched
+ *
+ * @todo Confirm the units of the "transferred" argument and then adjust
+ * name accordingly for clarity. Here I assume that it is the number of
+ * records successfully punched, in which case "records_punched" would
+ * be a more helpful name.
+ *
*/
int asg_punch (
asg_instance_t instance,
@@ -178,12 +425,35 @@ int asg_punch (
/**
- * Returns the number of entities that have been reset in reset_count
+ * Reset resets an entity (container, object, fork or record) to its
+ * original condition. It supports conditional execution based on the
+ * existing version number and given conditional flags. Reset differs from
+ * punch in that it reverts the version number back to zero
+ * in addition to removing data.
*
- * Passing ASG_RECORD_NULL resets all records in the fork.
- * Passing ASG_FORK_NULL resets all forks in the object.
- * Passing ASG_OBJECT_NULL resets all objects in the container.
- * Passing ASG_CONTAINER_NULL resets all containers in the storage system.
+ * @param[in] instance Interface instance
+ * @param[in] location Storage system location
+ * @param[in] container
+ * @param[in] object
+ * @param[in] fork
+ * @param[in] start_record First record in the contigous sequence to be
+ * reset
+ * @param[in] recordcount Number of records to be reset
+ * @param[in] recordlen
+ * @param[in] flags Flags to modify behavior or specify conditional modes
+ * @param[in] update_id_condition Update ID value to use for comparison
+ * tests in conditional mode
+ * @param[out] reset_count The number of records reset
+ *
+ * @note Reset can be used to reset more than just a specific set of
+ * records:
+ * - Passing ASG_RECORD_NULL resets all records in the fork.
+ * - Passing ASG_FORK_NULL resets all forks in the object.
+ * - Passing ASG_OBJECT_NULL resets all objects in the container.
+ * - Passing ASG_CONTAINER_NULL resets all containers in the storage system.
+ *
+ * @todo what does recordlen do in this context? It seems like an entity
+ * that has been reset to its initial state will always have a length of 0.
*/
int asg_reset (
asg_instance_t instance,
@@ -198,59 +468,67 @@ int asg_reset (
asg_update_id_t update_id_condition,
asg_size_t * reset_count);
+
/**
- * Probe retrieves information about containers, objects, forks or records.
- *
- * In all cases, start_item indicates the id of the first item (container,
- * object, fork or record) for which data should be retrieved.
- *
- * Buf points to a set of asg_container_info_t, asg_object_info_t,
- * asg_fork_info_t or asg_record_info_t structures.
- *
- * maxitems indicates the maximum number of info structures that should be
- * retrieved.
- *
- * transferred will contain the number of
- * structures stored in buf.
- *
- * returns
- * ASG_SUCCESS if all information was retrieved.
+ * Retrieve information about the containers present in a storage system.
+ * May be called iteratively to retrieve all containers if needed. It does
+ * not create a snapshot; the available set of containers may change between
+ * successive calls.
*
- * ASG_ERR_xxx
+ * @param[in] instance Interface instance
+ * @param[in] location Storage system location
+ * @param[in] start Container ID to begin probing from
+ * @param[out] buf array to be filled in with information describing
+ * containers
+ * @param[in] maxitems the number of elements in the buf array provided
+ * by the caller
+ * @param[out] transferred the number of elements in buf array filled in
+ * @param[out] next If more items are available, *next is set to the id of
+ * the next item for which information can be retrieved (and this value can
+ * be passed to 'start' in subsequent calls). If no more items are
+ * available then it will be set to ASG_CONTAINER_NULL.
*
- * If more items are available, *next is set to the id of the next item for
- * which information can be retrieved (and this value can be passed to 'start'
- * in subsequent calls).
- *
- * If no more items are available, *next is set to ASG_xxx_NULL
- *
- * Probe does not create a snapshot.
+ * @todo Is there any faster mechanism to use if the caller does not wish to
+ * retrieve the object count for each container in the system?
+ * @todo this function separates the incoming size of the array and outgoing
+ * size into separate arguments, unlike earlier functions in this header.
+ * Which convention do we want to use? We should be consistent.
*/
-
-typedef struct
-{
- asg_container_id_t container_id;
- asg_size_t seq_len;
- asg_size_t object_count; /* objects per container in the seq. */
-} asg_container_info_t;
-
int asg_probe_system (
asg_instance_t instance,
asg_location_t location,
asg_container_id_t start,
asg_container_info_t * buf,
asg_size_t maxitems,
- asg_size_t * transferred, /* number of container structures returned */
+ asg_size_t * transferred,
asg_container_id_t * next);
-
-typedef struct
-{
- asg_object_id_t object_id;
- asg_size_t seq_len;
- asg_size_t fork_count;
-} asg_object_info_t;
-
+/**
+ * Retrieve information about the objects present in a container.
+ * May be called iteratively to retrieve all objects if needed. It does
+ * not create a snapshot; the available set of objects may change between
+ * successive calls.
+ *
+ * @param[in] instance Interface instance
+ * @param[in] location Storage system location
+ * @param[in] container
+ * @param[in] start Object ID to begin probing from
+ * @param[out] buf array to be filled in with information describing
+ * objects
+ * @param[in] maxitems the number of elements in the buf array provided
+ * by the caller
+ * @param[out] transferred the number of elements in buf array filled in
+ * @param[out] next If more items are available, *next is set to the id of
+ * the next item for which information can be retrieved (and this value can
+ * be passed to 'start' in subsequent calls). If no more items are
+ * available then it will be set to ASG_OBJECT_NULL.
+ *
+ * @todo Is there any faster mechanism to use if the caller does not wish to
+ * retrieve the fork count for each object in a container?
+ * @todo this function separates the incoming size of the array and outgoing
+ * size into separate arguments, unlike earlier functions in this header.
+ * Which convention do we want to use? We should be consistent.
+ */
int asg_probe_container (
asg_instance_t instance,
asg_location_t location,
@@ -261,14 +539,33 @@ int asg_probe_container (
asg_size_t * transferred,
asg_object_id_t * next);
-
-typedef struct
-{
- asg_fork_id_t fork_id;
- asg_size_t seq_len;
- asg_size_t record_count;
-} asg_fork_info_t;
-
+/**
+ * Retrieve information about the forks present in an object.
+ * May be called iteratively to retrieve all forks if needed. It does
+ * not create a snapshot; the available set of forks may change between
+ * successive calls.
+ *
+ * @param[in] instance Interface instance
+ * @param[in] location Storage system location
+ * @param[in] container
+ * @param[in] object
+ * @param[in] start Fork ID to begin probing from
+ * @param[out] buf array to be filled in with information describing
+ * forks
+ * @param[in] maxitems the number of elements in the buf array provided
+ * by the caller
+ * @param[out] transferred the number of elements in buf array filled in
+ * @param[out] next If more items are available, *next is set to the id of
+ * the next item for which information can be retrieved (and this value can
+ * be passed to 'start' in subsequent calls). If no more items are
+ * available then it will be set to ASG_FORK_NULL.
+ *
+ * @todo Is there any faster mechanism to use if the caller does not wish to
+ * retrieve the record count for each fork in an object?
+ * @todo this function separates the incoming size of the array and outgoing
+ * size into separate arguments, unlike earlier functions in this header.
+ * Which convention do we want to use? We should be consistent.
+ */
int asg_probe_object (
asg_instance_t instance,
asg_location_t location,
@@ -280,6 +577,34 @@ int asg_probe_object (
asg_size_t * transferred,
asg_fork_id_t * next);
+/**
+ * Retrieve information about the records present in a fork.
+ * May be called iteratively to retrieve all records if needed. It does
+ * not create a snapshot; the available set of records may change between
+ * successive calls.
+ *
+ * @param[in] instance Interface instance
+ * @param[in] location Storage system location
+ * @param[in] container
+ * @param[in] object
+ * @param[in] fork
+ * @param[in] start Record ID to begin probing from
+ * @param[out] buf array to be filled in with information describing
+ * records
+ * @param[in] maxitems the number of elements in the buf array provided
+ * by the caller
+ * @param[out] transferred the number of elements in buf array filled in
+ * @param[out] next If more items are available, *next is set to the id of
+ * the next item for which information can be retrieved (and this value can
+ * be passed to 'start' in subsequent calls). If no more items are
+ * available then it will be set to ASG_RECORD_NULL.
+ *
+ * @todo Is there any faster mechanism to use if the caller does not wish to
+ * retrieve the record length for each record in a fork?
+ * @todo this function separates the incoming size of the array and outgoing
+ * size into separate arguments, unlike earlier functions in this header.
+ * Which convention do we want to use? We should be consistent.
+ */
int asg_probe_fork (
asg_instance_t instance,
asg_location_t location,
@@ -297,3 +622,5 @@ int asg_probe_fork (
#endif
#endif
+
+/* @} */
diff --git a/code/maint/depend-ae.sh b/code/maint/depend-ae.sh
index 988b843..70dbdd3 100755
--- a/code/maint/depend-ae.sh
+++ b/code/maint/depend-ae.sh
@@ -14,4 +14,4 @@ shift
if [ -n "$DIR" ] ; then
DIR="$DIR"/
fi
-exec $CC -x c -M -MM -MG $CFLAGS $1 | sed -e "s@^\(.*\)\.o:@$DIR\1.d $DIR\1.o :@"
+exec $CC -x c -M -MM -MG $CPPFLAGS $CFLAGS $1 | sed -e "s@^\(.*\)\.o:@$DIR\1.d $DIR\1.o :@"
diff --git a/code/sandbox/tosd/transactional-osd/transactional-osd.ae b/code/sandbox/tosd/transactional-osd/transactional-osd.ae
index eb98201..7ad0b32 100644
--- a/code/sandbox/tosd/transactional-osd/transactional-osd.ae
+++ b/code/sandbox/tosd/transactional-osd/transactional-osd.ae
@@ -116,6 +116,13 @@ static double read_time = 0;
#define COALESCE_DB 1
#define COALESCE_DATA 2
+/* parameters affecting how often to flush the BDB log files
+ * TODO: make run-time parameters
+ * currently a size threshold of 250MB (txn_checkpoint has kbyte units),
+ * and no time threshold */
+#define TOSD_DB_LOG_CHECKPOINT_TIME 0
+#define TOSD_DB_LOG_CHECKPOINT_SIZE ((250)*(1<<10))
+
#ifdef __TRITON_BDB_SI__
#define TXN_FLAGS DB_TXN_SNAPSHOT
#else
@@ -389,6 +396,9 @@ static __blocking triton_ret_t end_write(struct coalesce_obj *obj)
{
/* no coalescing */
triton_mutex_unlock(&coalesce_mutex);
+ /* conditionally flush the logs */
+ aebdb_txn_checkpoint(envp, TOSD_DB_LOG_CHECKPOINT_SIZE,
+ TOSD_DB_LOG_CHECKPOINT_TIME, 0);
return(TRITON_SUCCESS);
}
@@ -460,6 +470,10 @@ static __blocking triton_ret_t end_write(struct coalesce_obj *obj)
if(do_exit_flag)
coalesce_group_free(obj->group);
+ /* finally, conditionally flush the logs */
+ aebdb_txn_checkpoint(envp, TOSD_DB_LOG_CHECKPOINT_SIZE,
+ TOSD_DB_LOG_CHECKPOINT_TIME, 0);
+
return(TRITON_SUCCESS);
/* TODO: fill this in */
#if 0
@@ -1777,6 +1791,10 @@ triton_ret_t tosd_init(void)
ret = envp->set_cachesize(envp, 0, (100*1024*1024), 0);
assert(ret == 0);
+ /* we are auto-removing log files */
+ ret = envp->log_set_config(envp, DB_LOG_AUTO_REMOVE, 1);
+ assert(ret == 0);
+
env_flags =
DB_CREATE | /* Create the environment if it does not exist */
DB_RECOVER | /* Run normal recovery. */
diff --git a/code/scripts/jenkins/repos.fetch b/code/scripts/jenkins/repos.fetch
index f29dca1..f156f66 100644
--- a/code/scripts/jenkins/repos.fetch
+++ b/code/scripts/jenkins/repos.fetch
@@ -7,4 +7,4 @@
# tag is ok here too).
# mercury
-git git://git.mcs.anl.gov/radix/mercury mercury branch topic_callback
+git git://git.mcs.anl.gov/radix/mercury mercury branch next
diff --git a/code/src/admin-tools/triton-show-config.ae b/code/src/admin-tools/triton-show-config.ae
index 35a3f93..0944c79 100644
--- a/code/src/admin-tools/triton-show-config.ae
+++ b/code/src/admin-tools/triton-show-config.ae
@@ -16,7 +16,6 @@ __blocking int aesop_main(int argc, char **argv)
na_addr_t addr;
char* svr_string = NULL;
char* conf_buf = NULL;
- int conf_buf_size = 4*1024*1024;
if(argc != 1 && argc != 2)
{
@@ -48,21 +47,12 @@ __blocking int aesop_main(int argc, char **argv)
return(0);
}
- conf_buf = malloc(conf_buf_size);
- if(!conf_buf)
- {
- perror("malloc");
- triton_debug_finalize();
- return(-1);
- }
-
tret = triton_mercury_engine_init(TRITON_MERCURY_CLIENT, svr_string);
if(triton_is_error(tret))
{
triton_error_print(tret, "triton_mercury_engine_init()");
triton_error_destroy(tret);
triton_debug_finalize();
- free(conf_buf);
return(-1);
}
@@ -81,7 +71,6 @@ __blocking int aesop_main(int argc, char **argv)
triton_error_destroy(tret);
triton_mercury_engine_finalize();
triton_debug_finalize();
- free(conf_buf);
return(-1);
}
diff --git a/code/src/remote/core-rpc.ae b/code/src/remote/core-rpc.ae
index d916fea..549a069 100644
--- a/code/src/remote/core-rpc.ae
+++ b/code/src/remote/core-rpc.ae
@@ -23,11 +23,24 @@
static triton_mutex_t module_lock = TRITON_MUTEX_INITIALIZER;
static int module_refcount = 0;
+/* initial buffer size for config string */
+#define CONFIG_SZ_INIT (1<<12)
+/* extra padding to put into buffer on subsequent tries */
+#define CONFIG_SZ_EXTRA (1<<10)
+
+#if CONFIG_SZ_INIT < CONFIG_SZ_EXTRA
+#error "Bad buffering constants"
+#endif
+
/* generate input and output structs */
MERCURY_GEN_PROC(triton_rpc_noop_out_t, ((triton_ret_t)(tret)))
MERCURY_GEN_PROC(triton_rpc_getconfig_out_t,
- ((triton_ret_t)(tret))\
- ((hg_string_t)(cfg_str)))
+ ((triton_ret_t)(tret))\
+ ((uint64_t)(conf_size)))
+MERCURY_GEN_PROC(triton_rpc_getconfig_in_t,
+ ((uint64_t)(max_size))\
+ ((hg_bulk_t)(bulk_handle)))
+
/* TODO: temporary */
MERCURY_GEN_PROC(triton_rpc_shutdown_out_t, ((triton_ret_t)(tret)))
@@ -49,20 +62,58 @@ static void triton_rpc_noop_register(void);
static __blocking triton_ret_t triton_rpc_getconfig(hg_handle_t handle)
{
triton_rpc_getconfig_out_t out;
+ triton_rpc_getconfig_in_t in;
+ char * cfg_str;
+ uint64_t cfg_len;
+ struct hg_info *hg_info;
+ int ret;
+ triton_ret_t tret = TRITON_SUCCESS;
+ hg_bulk_t bulk_handle = HG_BULK_NULL;
triton_debug(triton_dbg_core_rpc, "Called triton_rpc_getconfig()\n");
- out.cfg_str = triton_zeroconf_serialize();
- if(!out.cfg_str)
+ triton_mercury_get_input(handle, &in, &out);
+
+ cfg_str = triton_zeroconf_serialize();
+ if(!cfg_str) {
+ /* TODO: should we internally return this as well? */
out.tret = TRITON_ERR_NOMEM;
- else
- out.tret = TRITON_SUCCESS;
+ goto end;
+ }
+ /* include the null char in the count */
+ cfg_len = strlen(cfg_str)+1;
+
+ if (cfg_len > in.max_size){
+ out.tret = TRITON_ERR_OVERFLOW;
+ out.conf_size = cfg_len;
+ goto end;
+ }
+ hg_info = HG_Get_info(handle);
+ ret = HG_Bulk_create(hg_info->hg_bulk_class, 1, (void**)&cfg_str,
+ &cfg_len, HG_BULK_READ_ONLY, &bulk_handle);
+ if (ret != HG_SUCCESS){
+ triton_error_msg("HG_Bulk_create failure\n");
+ out.tret = TRITON_ERR_UNKNOWN;
+ goto end;
+ }
+ ret = hg_rsc_bulk_transfer(hg_info->bulk_context, HG_BULK_PUSH,
+ hg_info->addr, in.bulk_handle, 0, bulk_handle, 0, cfg_len);
+ if (ret != HG_SUCCESS){
+ triton_error_msg("hg_rsc_bulk_transfer failure\n");
+ out.tret = TRITON_ERR_UNKNOWN;
+ goto end;
+ }
+ out.tret = TRITON_SUCCESS;
+ out.conf_size = cfg_len;
+
+end:
triton_mercury_respond(handle, &out);
- HG_Free_output(handle, &out);
HG_Destroy(handle);
+ if (bulk_handle != HG_BULK_NULL) HG_Bulk_free(bulk_handle);
+ if (cfg_str) free(cfg_str);
- return(TRITON_SUCCESS);
+ return tret;
}
TRITON_DEFINE_RPC_HANDLER(triton_rpc_getconfig)
@@ -123,7 +174,7 @@ static void triton_rpc_getconfig_register(void)
g_rpc_getconfig_id = MERCURY_REGISTER(hg_class,
"triton_rpc_getconfig_handler",
- void, triton_rpc_getconfig_out_t,
+ triton_rpc_getconfig_in_t, triton_rpc_getconfig_out_t,
triton_rpc_getconfig_handler);
return;
@@ -142,23 +193,48 @@ static void triton_rpc_noop_register(void)
}
__blocking triton_ret_t remote_triton_rpc_getconfig(na_addr_t addr,
- char** cfg_str)
+ char** cfg_str)
{
/* rpc params */
triton_rpc_getconfig_out_t out;
+ triton_rpc_getconfig_in_t in;
hg_handle_t handle = HG_HANDLE_NULL;
- int ret;
triton_ret_t tret;
-
- tret = TRITON_ERR_UNKNOWN;
- out.cfg_str = NULL;
-
- triton_mercury_run_rpc(addr, g_rpc_getconfig_id, handle, NULL, &out);
+ char * out_tmp = NULL;
+ uint64_t cfg_size;
+ out.conf_size = CONFIG_SZ_INIT - CONFIG_SZ_EXTRA;
+
+ /* NOTE: between successive calls to getconfig, the configuration can
+ * change. Hence:
+ * - we either get all or nothing - stitching together results from
+ * multiple calls is a recipe for inconsistency
+ * - we allocate a bit more than what the config call would have
+ * returned in the previous iteration in case the config grows between
+ * calls */
+ do {
+ cfg_size = out.conf_size + CONFIG_SZ_EXTRA;
+ free(out_tmp);
+ out_tmp = malloc(cfg_size);
+ if (!out_tmp){
+ perror("malloc");
+ return TRITON_ERR_NOMEM;
+ }
+ in.max_size = cfg_size;
+ in.bulk_handle = HG_BULK_NULL;
+ triton_mercury_run_rpc_with_bulk(addr, g_rpc_getconfig_id, handle, &in,
+ &out, in.bulk_handle, 1, &out_tmp, &cfg_size, 1, HG_BULK_WRITE_ONLY);
+ } while(out.tret == TRITON_ERR_OVERFLOW);
tret = triton_error_dup(out.tret);
- *cfg_str = (out.cfg_str) ? strdup(out.cfg_str) : NULL;
+
+ if (tret == TRITON_SUCCESS)
+ *cfg_str = out_tmp;
+ else {
+ *cfg_str = NULL;
+ if (out_tmp) free(out_tmp);
+ }
HG_Free_output(handle, &out);
HG_Destroy(handle);
diff --git a/code/src/remote/mercury-engine.ae b/code/src/remote/mercury-engine.ae
index f4c3703..654194e 100644
--- a/code/src/remote/mercury-engine.ae
+++ b/code/src/remote/mercury-engine.ae
@@ -147,6 +147,8 @@ void triton_mercury_engine_finalize(void)
hg_rsc_finalize();
HG_Context_destroy(hg_context);
+ NA_Context_destroy(network_class, na_context);
+ NA_Finalize(network_class);
hg_ret = HG_Finalize(hg_class);
if (hg_ret != HG_SUCCESS) {
diff --git a/code/src/remote/mercury-engine.hae b/code/src/remote/mercury-engine.hae
index cc7db6b..09d5e4a 100644
--- a/code/src/remote/mercury-engine.hae
+++ b/code/src/remote/mercury-engine.hae
@@ -77,7 +77,7 @@ do {\
} \
} while(0)
-#define triton_mercury_run_rpc_with_bulk(__addr, __rpc_id, __handle, __in_p, __out_p, __bulk_handle, __nbufs, __buffers, __sizes, __mode) \
+#define triton_mercury_run_rpc_with_bulk(__addr, __rpc_id, __handle, __in_p, __out_p, __bulk_handle, __nbufs, __buffers, __sizes, __del_buf_on_fail, __mode) \
do {\
int __ret; \
struct hg_info *__hg_info; \
@@ -86,18 +86,31 @@ do {\
triton_error_msg("triton_mercury_create_handle() failure\n"); \
return(TRITON_ERR_UNKNOWN); \
} \
- __hg_info = HG_Get_info(handle); \
- __ret = HG_Bulk_create(__hg_info->hg_bulk_class, __nbufs, __buffers, __sizes, __mode, &(__bulk_handle)); \
- if(__ret != HG_SUCCESS) { \
- triton_error_msg("HG_Bulk_create() failure.\n"); \
- HG_Destroy(__handle); \
- return(TRITON_ERR_UNKNOWN); \
+ if(__nbufs > 1 || (__sizes)[0] > 0) { \
+ __hg_info = HG_Get_info(handle); \
+ __ret = HG_Bulk_create(__hg_info->hg_bulk_class, __nbufs, __buffers, __sizes, __mode, &(__bulk_handle)); \
+ if(__ret != HG_SUCCESS) { \
+ triton_error_msg("HG_Bulk_create() failure.\n"); \
+ HG_Destroy(__handle); \
+ if (__del_buf_on_fail){\
+ int __i; \
+ for(__i=0; __i<__nbufs; __i++) free((__buffers)[__i]); \
+ }\
+ return(TRITON_ERR_UNKNOWN); \
+ }\
+ }\
+ else {\
+ __bulk_handle = HG_BULK_NULL; \
}\
__ret = hg_rsc_forward(__handle, (__in_p)); \
if(__ret != HG_SUCCESS) { \
triton_error_msg("hg_rsc_forward() failure.\n"); \
HG_Bulk_free(__bulk_handle); \
HG_Destroy(__handle); \
+ if (__del_buf_on_fail){\
+ int __i; \
+ for(__i=0; __i<__nbufs; __i++) free((__buffers)[__i]); \
+ }\
return(TRITON_ERR_UNKNOWN); \
} \
__ret = HG_Get_output(__handle, (__out_p)); \
@@ -105,6 +118,10 @@ do {\
triton_error_msg("HG_Get_output() failure.\n"); \
HG_Bulk_free(__bulk_handle); \
HG_Destroy(__handle); \
+ if (__del_buf_on_fail){\
+ int __i; \
+ for(__i=0; __i<__nbufs; __i++) free((__buffers)[__i]); \
+ }\
return(TRITON_ERR_UNKNOWN); \
} \
HG_Bulk_free(__bulk_handle); \
diff --git a/code/src/remote/mercury-rsc.c b/code/src/remote/mercury-rsc.c
index 449e538..b290fb2 100644
--- a/code/src/remote/mercury-rsc.c
+++ b/code/src/remote/mercury-rsc.c
@@ -178,6 +178,7 @@ void hg_rsc_finalize(
hg_progress_waiting = 0;
hg_progress_shutdown = 1;
}
+ pthread_barrier_destroy(&hg_resource_barrier);
}
triton_mutex_unlock(&hg_rsc_refcount_mutex);
@@ -248,8 +249,6 @@ static void* hg_progress_fn(void* foo)
pthread_barrier_wait(&hg_resource_barrier);
}
- pthread_barrier_destroy(&hg_resource_barrier);
-
return(NULL);
}
diff --git a/code/src/replicated-osd/rosd-alloc.ae b/code/src/replicated-osd/rosd-alloc.ae
index bace7b3..88fb277 100644
--- a/code/src/replicated-osd/rosd-alloc.ae
+++ b/code/src/replicated-osd/rosd-alloc.ae
@@ -119,7 +119,7 @@ __blocking triton_ret_t remote_triton_rpc_rosd_alloc(
bulk_sz = (size_t)num_objects * (size_t)replicas * sizeof(uint64_t);
triton_mercury_run_rpc_with_bulk(addr, rpc_rosd_alloc_id, handle, &in,
- &out, in.bulk_handle, 1, (void**)&objects, &bulk_sz, HG_BULK_WRITE_ONLY);
+ &out, in.bulk_handle, 1, (void**)&objects, &bulk_sz, 0, HG_BULK_WRITE_ONLY);
triton_mercury_addr_free(addr);
diff --git a/code/src/replicated-osd/rosd-read.ae b/code/src/replicated-osd/rosd-read.ae
index 797ea40..43c6ec1 100644
--- a/code/src/replicated-osd/rosd-read.ae
+++ b/code/src/replicated-osd/rosd-read.ae
@@ -93,7 +93,7 @@ __blocking triton_ret_t remote_triton_rpc_rosd_read(
bulk_sizes[1] = recordcount * sizeof(*record_info);
triton_mercury_run_rpc_with_bulk(addr, rpc_rosd_read_id, handle,
- &in, &out, in.bulk_handle, 2, bulk_bufs, bulk_sizes,
+ &in, &out, in.bulk_handle, 2, bulk_bufs, bulk_sizes, 0,
HG_BULK_WRITE_ONLY);
triton_mercury_addr_free(addr);
diff --git a/code/src/replicated-osd/rosd-write.ae b/code/src/replicated-osd/rosd-write.ae
index 89a6d40..883b5d5 100644
--- a/code/src/replicated-osd/rosd-write.ae
+++ b/code/src/replicated-osd/rosd-write.ae
@@ -563,7 +563,7 @@ static __blocking triton_ret_t __remote_triton_rpc_rosd_write(
in.bulk_handle = HG_BULK_NULL;
triton_mercury_run_rpc_with_bulk(addr, rpc_rosd_write_id, handle,
- &in, &out, in.bulk_handle, 1, &data, &bulk_size, HG_BULK_READ_ONLY);
+ &in, &out, in.bulk_handle, 1, &data, &bulk_size, 0, HG_BULK_READ_ONLY);
tret = triton_error_dup(out.tret);
diff --git a/code/src/system-state/system-state.ae b/code/src/system-state/system-state.ae
index a74160b..7ea9de9 100644
--- a/code/src/system-state/system-state.ae
+++ b/code/src/system-state/system-state.ae
@@ -10,6 +10,15 @@
#include "src/remote/mercury-engine.hae"
#include "src/remote/mercury-encode.h"
+/* initial buffer size for snapshot string */
+#define SNAP_SZ_INIT (1<<12)
+/* extra padding to put into buffer on subsequent tries */
+#define SNAP_SZ_EXTRA (1<<10)
+
+#if SNAP_SZ_INIT < SNAP_SZ_EXTRA
+#error "Bad buffering constants"
+#endif
+
/* state information for a particular key */
struct key_type
{
@@ -28,7 +37,12 @@ struct state_entry
};
/* generate input and output structs */
-MERCURY_GEN_PROC(triton_rpc_system_state_get_snapshot_out_t, ((triton_ret_t)(tret))((hg_string_t)(serialized)))
+MERCURY_GEN_PROC(triton_rpc_system_state_get_snapshot_out_t,
+ ((triton_ret_t)(tret))\
+ ((uint64_t)(state_size)))
+MERCURY_GEN_PROC(triton_rpc_system_state_get_snapshot_in_t,
+ ((uint64_t)(max_size))\
+ ((hg_bulk_t)(bulk_handle)))
static hg_id_t g_rpc_get_snapshot_id;
static hg_return_t
@@ -376,23 +390,61 @@ triton_ret_t system_state_list_nodes(const char* key, triton_node_t** node_array
static __blocking triton_ret_t triton_rpc_system_state_get_snapshot(hg_handle_t handle)
{
triton_rpc_system_state_get_snapshot_out_t out;
+ triton_rpc_system_state_get_snapshot_in_t in;
+ char * state_str;
+ uint64_t state_len;
+ struct hg_info *hg_info;
+ int ret;
+ triton_ret_t tret = TRITON_SUCCESS;
+ hg_bulk_t bulk_handle = HG_BULK_NULL;
triton_debug(triton_dbg_core_rpc, "Called triton_rpc_system_state_get_snapshot()\n");
+ triton_mercury_get_input(handle, &in, &out);
+
/* Fill output structure */
- out.serialized = system_state_serialize();
- if(out.serialized)
- out.tret = TRITON_SUCCESS;
- else
+ state_str = system_state_serialize();
+ if(!state_str) {
+ /* TODO: should we internally return this as well? */
+ out.tret = TRITON_ERR_NOMEM;
+ goto end;
+ }
+
+ /* include the null char in the count */
+ state_len = strlen(state_str)+1;
+
+ if (state_len > in.max_size) {
+ out.tret = TRITON_ERR_OVERFLOW;
+ out.state_size = state_len;
+ goto end;
+ }
+
+ hg_info = HG_Get_info(handle);
+ ret = HG_Bulk_create(hg_info->hg_bulk_class, 1, (void**)&state_str,
+ &state_len, HG_BULK_READ_ONLY, &bulk_handle);
+ if (ret != HG_SUCCESS){
+ triton_error_msg("HG_Bulk_create failure\n");
out.tret = TRITON_ERR_UNKNOWN;
+ goto end;
+ }
+ ret = hg_rsc_bulk_transfer(hg_info->bulk_context, HG_BULK_PUSH,
+ hg_info->addr, in.bulk_handle, 0, bulk_handle, 0, state_len);
+ if (ret != HG_SUCCESS){
+ triton_error_msg("hg_rsc_bulk_transfer failure\n");
+ out.tret = TRITON_ERR_UNKNOWN;
+ goto end;
+ }
+ out.tret = TRITON_SUCCESS;
+ out.state_size = state_len;
+end:
triton_mercury_respond(handle, &out);
-
/* cleanup */
- HG_Free_output(handle, &out);
HG_Destroy(handle);
+ if (bulk_handle != HG_BULK_NULL) HG_Bulk_free(bulk_handle);
+ if (state_str) free(state_str);
- return(TRITON_SUCCESS);
+ return tret;
}
TRITON_DEFINE_RPC_HANDLER(triton_rpc_system_state_get_snapshot)
@@ -404,7 +456,8 @@ void triton_rpc_system_state_register(void)
g_rpc_get_snapshot_id = MERCURY_REGISTER(hg_class,
"triton_rpc_system_state_get_snapshot",
- void, triton_rpc_system_state_get_snapshot_out_t,
+ triton_rpc_system_state_get_snapshot_in_t,
+ triton_rpc_system_state_get_snapshot_out_t,
triton_rpc_system_state_get_snapshot_handler);
}
@@ -412,25 +465,50 @@ void triton_rpc_system_state_register(void)
__blocking triton_ret_t remote_triton_rpc_system_state_get_snapshot(na_addr_t addr, char** serialized)
{
triton_rpc_system_state_get_snapshot_out_t out;
+ triton_rpc_system_state_get_snapshot_in_t in;
int ret;
hg_handle_t handle = HG_HANDLE_NULL;
triton_ret_t tret = TRITON_ERR_UNKNOWN;
-
- triton_mercury_run_rpc(addr, g_rpc_get_snapshot_id, handle, NULL, &out);
+ char * out_tmp = NULL;
+ uint64_t state_size;
+ out.state_size = SNAP_SZ_INIT - SNAP_SZ_EXTRA;
+
+ /* NOTE: between successive calls to get_snapshot, the state can
+ * change. Hence:
+ * - we either get all or nothing - stitching together results from
+ * multiple calls is a recipe for inconsistency
+ * - we allocate a bit more than what the snapshot call would have
+ * returned in the previous iteration in case the state grows between
+ * calls */
+ do {
+ state_size = out.state_size + SNAP_SZ_EXTRA;
+ free(out_tmp);
+ out_tmp = malloc(state_size);
+ if (!out_tmp){
+ perror("malloc");
+ return TRITON_ERR_NOMEM;
+ }
+ in.max_size = state_size;
+ in.bulk_handle = HG_BULK_NULL;
+ triton_mercury_run_rpc_with_bulk(addr, g_rpc_get_snapshot_id, handle,
+ &in, &out, in.bulk_handle, 1, &out_tmp, &state_size, 1,
+ HG_BULK_WRITE_ONLY);
+ } while(out.tret == TRITON_ERR_OVERFLOW);
tret = triton_error_dup(out.tret);
- *serialized = strdup(out.serialized);
- if(!(*serialized))
- {
- triton_error_destroy(tret);
- tret = TRITON_ERR_NOMEM;
+ if (tret == TRITON_SUCCESS)
+ *serialized = out_tmp;
+ else {
+ *serialized = NULL;
+ if (out_tmp) free(out_tmp);
}
HG_Free_output(handle, &out);
HG_Destroy(handle);
- return(tret);
+
+ return tret;
}
/*
diff --git a/code/tests/Makefile.subdir b/code/tests/Makefile.subdir
index 29e19ea..570a3f9 100644
--- a/code/tests/Makefile.subdir
+++ b/code/tests/Makefile.subdir
@@ -12,7 +12,8 @@ check_PROGRAMS += \
tests/common/test-debug \
tests/placement/test-placement \
tests/system-state/test-system-state \
- tests/asg/test-asg-simple
+ tests/asg/test-asg-simple \
+ tests/asg/test-asg-multi-init
#TODO: REPLACEME
#tests/transactional-osd/tosd1
@@ -38,7 +39,8 @@ TESTS += \
tests/placement/test-placement-mrh.sh \
tests/common/test-debug.sh \
tests/system-state/test-system-state \
- tests/asg/test-asg-simple.sh
+ tests/asg/test-asg-simple.sh \
+ tests/asg/test-asg-multi-init.sh
#TODO: REPLACEME
#tests/transactional-osd/tosd1
@@ -56,6 +58,7 @@ AE_SRC += tests/placement/test-placement.ae \
tests_common_test_triton_ret_t_SOURCES = tests/common/test-triton-ret-t.c
tests_common_test_debug_SOURCES = tests/common/test-debug.c
tests_asg_test_asg_simple_SOURCES = tests/asg/test-asg-simple.c
+tests_asg_test_asg_multi_init_SOURCES = tests/asg/test-asg-multi-init.c
#tests_transactional_osd_bdb_snapshot_write_SOURCES = tests/transactional-osd/bdb-snapshot-write.c
EXTRA_DIST += \
diff --git a/code/tests/asg/test-asg-multi-init.c b/code/tests/asg/test-asg-multi-init.c
new file mode 100644
index 0000000..80b762a
--- /dev/null
+++ b/code/tests/asg/test-asg-multi-init.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "include/asg.h"
+
+int main(int argc, char **argv)
+{
+ int ret;
+ asg_instance_t ait;
+ int i;
+
+ if(argc != 2)
+ {
+ fprintf(stderr, "Usage: test-asg-multi-init <server address>\n");
+ fprintf(stderr, " example: ./test-asg-simple tcp://localhost:3344\n");
+ return(-1);
+ }
+
+ /* cycle through some number of init/fini's */
+ for (i = 0; i < 20; i++) {
+ ret = asg_initialize(&ait, argv[1]);
+ if(ret != ASG_SUCCESS)
+ {
+ fprintf(stderr, "Error: asg_initialize(..., \"%s\")\n", argv[1]);
+ return(-1);
+ }
+
+ ret = asg_finalize(ait);
+ if(ret != ASG_SUCCESS)
+ {
+ fprintf(stderr, "Error: asg_finalize()\n");
+ return(-1);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
diff --git a/code/tests/asg/test-asg-simple.sh b/code/tests/asg/test-asg-multi-init.sh
similarity index 91%
copy from code/tests/asg/test-asg-simple.sh
copy to code/tests/asg/test-asg-multi-init.sh
index 18af42f..cfe1246 100755
--- a/code/tests/asg/test-asg-simple.sh
+++ b/code/tests/asg/test-asg-multi-init.sh
@@ -11,7 +11,7 @@ test_start_servers 1 5 60 1
# actual test case
#####################
-run_to 60 tests/asg/test-asg-simple $svr1 555
+run_to 60 tests/asg/test-asg-multi-init $svr1
if [ $? -ne 0 ]; then
run_to 60 src/admin-tools/triton-shutdown-all-servers $svr1 &> /dev/null
wait
diff --git a/misc/experiments/ior-asg/README b/misc/experiments/ior-asg/README
index e2ebc17..5fb86b4 100644
--- a/misc/experiments/ior-asg/README
+++ b/misc/experiments/ior-asg/README
@@ -5,7 +5,10 @@ ior-run.sh is a script intended for linux cluster systems for
See usage for details.
-Experiment requires the ASG-enabled IOR benchmark.
+Experiment requires the ASG-enabled IOR benchmark, as well as IOR-utils.
+IOR-utils in particular can be found at:
+
+https://github.com/JohnPJenkins/ior-utils
For an example usage on a Cobalt-enabled cluster, see the run-tukey-example.sh
script and the example_input directory.
diff --git a/misc/experiments/ior-asg/example_input/ior_asg.conf.many.template b/misc/experiments/ior-asg/example_input/ior_asg.conf.many.template
new file mode 100644
index 0000000..853ea3f
--- /dev/null
+++ b/misc/experiments/ior-asg/example_input/ior_asg.conf.many.template
@@ -0,0 +1,18 @@
+IOR START
+ api=ASG
+ repetitions=10
+ verbose=0
+ segmentCount=16
+ blockSize=XFER_SIZE
+ transferSize=XFER_SIZE
+ numTasks=NUM_TASKS
+ fsync=0
+ writeFile=1
+ readFile=1
+ keepFile=0
+ filePerProc=FILE_PER_PROC
+ testFile = TRITON_HOST:data.dat
+ useExistingTestFile=0
+ fsyncPerWrite=1
+ RUN
+IOR STOP
diff --git a/misc/experiments/ior-asg/example_input/ior_asg.conf.template b/misc/experiments/ior-asg/example_input/ior_asg.conf.template
index 9ca69b3..b07471c 100644
--- a/misc/experiments/ior-asg/example_input/ior_asg.conf.template
+++ b/misc/experiments/ior-asg/example_input/ior_asg.conf.template
@@ -8,10 +8,10 @@ IOR START
fsync=0
writeFile=1
readFile=1
- keepFile=1
+ keepFile=0
filePerProc=0
testFile = REPLACEME:shared.dat
- useExistingTestFile=1
+ useExistingTestFile=0
fsyncPerWrite=1
RUN
IOR STOP
diff --git a/misc/experiments/ior-asg/ior-run.sh b/misc/experiments/ior-asg/ior-run.sh
index 18c97a1..42eee8f 100755
--- a/misc/experiments/ior-asg/ior-run.sh
+++ b/misc/experiments/ior-asg/ior-run.sh
@@ -8,6 +8,11 @@ function assert_error () {
fi
}
+function die () {
+ echo $@ >&2
+ exit 1
+}
+
function usage () {
local app=$(basename $0)
cat >&2 <<EOF
@@ -16,9 +21,12 @@ usage: $app [-h] [-e <path to triton executables>]
[-c <triton config template>]
[-s <triton storage directory>]
[-x <IOR executable path>]
+ [-U <token + values for IOR script>]
+ [-u <IOR utils path>]
[-p <ranks per node>]
[-w]
- [-d <tempfile dir>]
+ [-d <output dir>]
+ [-t <mpirun timeout>]
[-i <temp ID>]
[-r <replication factor>]
<num clients> <host file>
@@ -32,17 +40,25 @@ usage: $app [-h] [-e <path to triton executables>]
generate-config.sh)
-s optional directory to place triton server data/metadata
files (see generate-config.sh)
- -x IOR execuable path
+ -x IOR executable path
(default - assumes the executable is on PATH)
+ -U use IOR utils to generate the IOR config file with the given
+ space-delimited set of <token value value ...> strings
+ -U can be specified multiple times for multiple replace passes
+ -u IOR utils path
+ (default - assumes the utils are in PATH)
-p processes per client node to run IOR on
(default - 1)
-w run a parameter sweep over the number of clients, in
an exponential progression (1, 2, 4, 8, ... num_clients)
- -t path where job temporaries + output will be placed.
+ -d path where job temporaries + output will be placed.
This location must be reachable by all nodes in the
job. This location will be created via mkdir -p if it
doesn't exist.
(default - current working directory)
+ -t timeout to kill each IOR mpirun (in case of hangs or other
+ problems)
+ (default: no timeout)
-i temporary ID to use with temp files
(default - none)
-r replication factor for each object created
@@ -60,12 +76,14 @@ The IOR template is expected to be in the following format:
===
IOR START
... options ...
- testFile = REPLACEME:filename
+ numTasks = NUM_TASKS
+ testFile = TRITON_HOST:filename
... options ...
IOR STOP
===
-The token REPLACEME will be replaced with a valid triton
-host.
+The token NUM_TASKS will be replaced with the number of
+ranks used (based on num_clients, ppn), whereas TRITON_HOST
+will be replaced with a valid triton host.
NOTE: assumes IOR config file properly directs the output
files to an appropriate location
@@ -79,35 +97,47 @@ g_triton_template=
g_triton_storage_path=
g_working_path=$(pwd)
g_ior_exe=
+g_ior_util_path=
+g_ior_util_opt_arr=()
g_ior_ppn=1
g_temp_id=
g_repfactor=1
g_do_sweep=no
-while getopts :he:m:c:s:x:p:wt:i:r: flag ; do
+g_timeout=no
+while getopts :he:m:c:s:x:U:u:p:wd:t:i:r: flag ; do
case $flag in
- h) usage
+ h) usage
+ ;;
+ e) g_triton_exe_path=${OPTARG%%/}
;;
- e) g_triton_exe_path=${OPTARG%%/}
+ m) g_triton_mgmt_path=${OPTARG%%/}
;;
- m) g_triton_mgmt_path=${OPTARG%%/}
+ c) g_triton_template=$OPTARG
;;
- c) g_triton_template=$OPTARG
+ s) g_triton_storage_path=${OPTARG%%/}
;;
- s) g_triton_storage_path=${OPTARG%%/}
+ x) g_ior_exe=$OPTARG
;;
- x) g_ior_exe=$OPTARG
+ U) l_len=${#g_ior_util_opt_arr[@]}
+ g_ior_util_opt_arr[$((l_len+1))]="$OPTARG"
;;
- p) g_ior_ppn=${OPTARG%%/}
+ u) g_ior_util_path=${OPTARG}
;;
- w) g_do_sweep=yes
+ p) g_ior_ppn=${OPTARG%%/}
;;
- t) g_working_path=${OPTARG%%/}
+ w) g_do_sweep=yes
;;
- i) g_temp_id=.$OPTARG
+ d) g_working_path=${OPTARG%%/}
;;
- r) g_repfactor=$OPTARG
+ t) g_timeout=${OPTARG}
+ timeout $g_timeout echo >/dev/null 2>/dev/null \
+ || die "invalid timeout (-t) value ($g_timeout)"
;;
- ?) echo Unrecognized option: $OPTARG
+ i) g_temp_id=.$OPTARG
+ ;;
+ r) g_repfactor=$OPTARG
+ ;;
+ ?) echo Unrecognized option: $OPTARG
esac
done
@@ -124,19 +154,16 @@ set -u
### check the input
if ! [[ $g_num_clients =~ [1-9][0-9]* ]] ; then
- echo Argument $g_num_clients expected to be a positive number of clients >&2
- exit 1
+ die "Argument $g_num_clients expected to be a positive number of clients"
fi
# check for existence of the ior template
if ! [[ -r $g_ior_template ]] ; then
- echo File $g_ior_template cannot be found / is not readable >&2
- exit 1
+ die "File $g_ior_template cannot be found / is not readable"
fi
# check for the host file
if ! [[ -r $g_host_file ]] ; then
- echo File $g_host_file cannot be found / is not readable >&2
- exit 1
+ die "File $g_host_file cannot be found / is not readable"
fi
# check for the automation scripts
@@ -144,20 +171,17 @@ fi
g_script_prefix=$g_triton_mgmt_path/ || g_script_prefix=
if ! [[ -x ${g_script_prefix}start-servers.sh ]] ; then
- echo Could not find executable ${g_script_prefix}start-servers.sh >&2
- exit 1
+ die "Could not find executable ${g_script_prefix}start-servers.sh"
fi
# check for sane ppn
if ! [[ $g_ior_ppn =~ ^[1-9][0-9]*$ ]] ; then
- echo Invalid processes per node: $g_ior_ppn >&2
- exit 1
+ die "Invalid processes per node: $g_ior_ppn"
fi
# check for the IOR executable
if [[ ! -x $g_ior_exe ]] ; then
- echo "Could not find ior executable ($g_ior_exe)" >&2
- exit 1
+ die "Could not find ior executable ($g_ior_exe)"
fi
### input checking done
@@ -197,61 +221,103 @@ ${g_script_prefix}generate-config.sh \
> $g_triton_cfg_file
assert_error
-### start up the servers
-
-[[ -n $g_triton_exe_path ]] && \
- g_triton_exe_path_arg="-t $g_triton_exe_path" || g_triton_exe_path_arg=
-
-${g_script_prefix}start-servers.sh \
- $g_triton_exe_path_arg $g_triton_cfg_file
-assert_error
-
-### quick check - ensure that triton processes are running on the servers
-### TODO: this is really a hack, probably shouldn't rely on it
-for host in $(cat $g_hostfile_tmp) ; do
- if [[ -z $(ssh $host pgrep triton-server 2>/dev/null) ]] ; then
- echo couldnt find triton server process!! >&2
- exit 1
- fi
-done
-
-### servers are ready to go - generate the IOR script and kick it off
+### generate the IOR runs
# for now, we're just grabbing the first host from the config - we should
# probably think harder about how this works to avoid bottlenecking
g_ior_cfg=$g_working_path/ior${g_temp_id}.tmp
+g_ior_replace=
# note: need parse hosts here instead of head g_hostfile_tmp for the "decorated"
# hostname
g_ior_init_hostname=\
$(${g_script_prefix}parse-hosts.sh -n $g_triton_cfg_file | head -n 1)
assert_error
-sed "s!REPLACEME!asg:$g_ior_init_hostname!" < $g_ior_template > $g_ior_cfg
-# set up potential parameter sweep client counts
-i=$((g_num_clients*g_ior_ppn))
+# try to find the util script
+if [[ $g_ior_util_path != "" && -x $g_ior_util_path/replace_many.sh ]] ; then
+ g_ior_replace="$g_ior_util_path"/replace_many.sh
+else
+ g_ior_replace=$(which replace_many.sh 2> /dev/null)
+fi
+[[ -x $g_ior_replace ]] || die "couldn't find ior util scripts"
+
+# create the num_task replacements
if [[ $g_do_sweep == yes ]] ; then
i=1
else
i=$((g_num_clients*g_ior_ppn))
fi
-# run it!!!
# TODO: better way of controlling rank to node mapping?
+g_ntask_list="NUM_TASKS"
for (( ; i <= $g_num_clients*$g_ior_ppn ; i*=2 )) ; do
- timeout 3m mpirun -n $i -f $g_clifile_tmp \
- $g_ior_exe -f $g_ior_cfg \
- >> $g_working_path/ior.$i${g_temp_id}.out \
- 2>> $g_working_path/ior.$i${g_temp_id}.err
- err=$? ; [[ $err == 0 ]] || ( echo mpirun failed, exiting... >&2 ; break )
+ g_ntask_list+=" $i"
+done
+l_len=${#g_ior_util_opt_arr[@]}
+g_ior_util_opt_arr[$((l_len+1))]="$g_ntask_list"
+
+# use tempfiles to process multiple generation passes
+l_tmpf=$(mktemp)
+assert_error
+l_currf=$g_ior_template
+for replace_args in "${g_ior_util_opt_arr[@]}" ; do
+ $g_ior_replace $replace_args < $l_currf > $l_tmpf
+ assert_error
+ [[ $l_currf == $g_ior_template ]] || rm $l_currf
+ l_currf=$l_tmpf
+ l_tmpf=$(mktemp)
+ assert_error
+done
+rm $l_tmpf
+# finally drop in the initial triton contact point
+sed "s!TRITON_HOST!asg:$g_ior_init_hostname!g" < $l_currf > $g_ior_cfg
+[[ $l_currf == $g_ior_template ]] || rm $l_currf
+
+### start up the servers
+
+[[ -n $g_triton_exe_path ]] && \
+ g_triton_exe_path_arg="-t $g_triton_exe_path" || g_triton_exe_path_arg=
+
+mkdir -p "$g_working_path/server_output"
+${g_script_prefix}start-servers.sh \
+ -d "$g_working_path/server_output" $g_triton_exe_path_arg \
+ $g_triton_cfg_file
+assert_error
+
+### quick check - ensure that triton processes are running on the servers
+### TODO: this is really a hack, probably shouldn't rely on it
+for host in $(cat $g_hostfile_tmp) ; do
+ if [[ -z $(ssh $host pgrep triton-server 2>/dev/null) ]] ; then
+ die "couldnt find triton server process!!"
+ fi
done
+[[ $g_timeout == no ]] \
+ && g_timeout_cmd= \
+ || g_timeout_cmd="timeout $g_timeout"
+
+# run it!!!
+# (since proc counts are part of the IOR input now, no need
+# to loop over multiple calls)
+$g_timeout_cmd mpirun -n $((g_num_clients*g_ior_ppn)) -f $g_clifile_tmp \
+ $g_ior_exe -f $g_ior_cfg \
+ >> $g_working_path/ior${g_temp_id}.out \
+ 2>> $g_working_path/ior${g_temp_id}.err
+err=$?
+if [[ $err == 124 ]] ; then
+ echo mpirun timed out, exiting... >&2
+elif [[ $err != 0 ]] ; then
+ echo mpirun failed for unknown reason, exiting... >&2
+fi
+
### shutdown the servers and perform cleanup
# files to delete on success
[[ -z $g_triton_storage_path ]] \
&& g_triton_store=/tmp || g_triton_store=$g_triton_storage_path
g_file_glob="$g_triton_store/triton-server-*"
+g_log_glob="${g_file_glob}-log"
g_file_glob="$g_file_glob-data $g_file_glob-meta ${g_file_glob}-log"
shutdown_cmd=triton-shutdown-all-servers
@@ -265,6 +331,11 @@ if [[ $err == 0 ]] ; then
for host in $(${g_script_prefix}parse-hosts.sh -u $g_triton_cfg_file) ; do
ssh $host rm -rf "$g_file_glob"
done
+else
+ # get the logs
+ for host in $(${g_script_prefix}parse-hosts.sh -u $g_triton_cfg_file) ; do
+ scp $host:"$g_log_glob" "$g_working_path/server_output"
+ done
fi
exit $err
diff --git a/misc/experiments/ior-asg/run-tukey-example.sh b/misc/experiments/ior-asg/run-tukey-example.sh
index 9771b3e..b2a39ae 100755
--- a/misc/experiments/ior-asg/run-tukey-example.sh
+++ b/misc/experiments/ior-asg/run-tukey-example.sh
@@ -18,9 +18,10 @@ g_triton_exe_path=$g_base/install/bin
g_triton_script_path=$g_base/triton/code/scripts/simple-mgmt
g_triton_cfg=$g_path_to_run/example_input/triton_ior.conf.template
g_ior=$g_base/ior/build/src/ior
+g_ior_utils=$g_base/ior-utils
g_tmp=$HOME/ior-asg-$COBALT_JOBID
mkdir -p $g_tmp
-g_ior_cfg=$g_path_to_run/example_input/ior_asg.conf.template
+g_ior_cfg=$g_path_to_run/example_input/ior_asg.conf.many.template
g_num_nodes=$(wc -l < $COBALT_NODEFILE)
if [[ -z $1 || ! $1 =~ ^[1-9][0-9]*$ || ! $1 -lt $g_num_nodes ]] ; then
@@ -34,9 +35,12 @@ $g_path_to_run/ior-run.sh \
-s /dev/shm \
-x $g_ior \
-p 16 \
- -t $g_tmp \
- -i $COBALT_JOBID \
- -r 3 \
+ -u $g_ior_utils \
+ -U "XFER_SIZE 8 32 128 512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M" \
+ -U "FILE_PER_PROC 0" \
+ -w \
+ -d $g_tmp \
+ -r 1 \
$1 \
$COBALT_NODEFILE \
$g_ior_cfg
hooks/post-receive
--
1
0
21 Jan '15
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, master has been updated
via 9c9d7b4da56fbac8bd3b1258198026ec6d0d91e2 (commit)
from cdf42d8449873a456fd06e7ee2e3f364b1db317b (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 9c9d7b4da56fbac8bd3b1258198026ec6d0d91e2
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Wed Jan 21 20:54:45 2015 -0500
propagate CFLAGS fixes from John to triton repo
-----------------------------------------------------------------------
Summary of changes:
code/Make.rules | 8 ++++----
code/maint/depend-ae.sh | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
Diff of changes:
diff --git a/code/Make.rules b/code/Make.rules
index c20bca5..bc9c96c 100644
--- a/code/Make.rules
+++ b/code/Make.rules
@@ -15,10 +15,10 @@ tests: $(check_PROGRAMS)
# rule for compiling aesop .ae files
#
.ae.o:
- $(AM_V_GEN)$(AECC) -o $@ $< -- $(CFLAGS)
+ $(AM_V_GEN)$(AECC) -o $@ $< -- $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $(AM_CFLAGS)
.hae.h:
- $(AM_V_GEN)$(AECC) -o $@ $< -j -- $(CFLAGS)
+ $(AM_V_GEN)$(AECC) -o $@ $< -j -- $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $(AM_CFLAGS)
#
# rules for .ae dependencies
@@ -27,11 +27,11 @@ dirname = $(patsubst %/,%,$(dir $(1)))
%.ae.d: %.ae
mkdir -p $(call dirname,$@)
- $(AM_V_GEN)CC="$(CC)" CFLAGS="$(CFLAGS)" $(srcdir)/maint/depend-ae.sh $(call dirname,$@) $< > $@
+ $(AM_V_GEN)CC="$(CC)" CPPFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS)" CFLAGS="$(AM_CFLAGS) $(CFLAGS)" $(srcdir)/maint/depend-ae.sh $(call dirname,$@) $< > $@
%.hae.d: %.hae
mkdir -p $(call dirname,$@)
- $(AM_V_GEN)CC="$(CC)" CFLAGS="$(CFLAGS)" $(srcdir)/maint/depend-ae.sh $(call dirname,$@) $< > $@
+ $(AM_V_GEN)CC="$(CC)" CPPFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS)" CFLAGS="$(AM_CFLAGS) $(CFLAGS)" $(srcdir)/maint/depend-ae.sh $(call dirname,$@) $< > $@
#============================================================================
# Asciidoc rules
diff --git a/code/maint/depend-ae.sh b/code/maint/depend-ae.sh
index 988b843..70dbdd3 100755
--- a/code/maint/depend-ae.sh
+++ b/code/maint/depend-ae.sh
@@ -14,4 +14,4 @@ shift
if [ -n "$DIR" ] ; then
DIR="$DIR"/
fi
-exec $CC -x c -M -MM -MG $CFLAGS $1 | sed -e "s@^\(.*\)\.o:@$DIR\1.d $DIR\1.o :@"
+exec $CC -x c -M -MM -MG $CPPFLAGS $CFLAGS $1 | sed -e "s@^\(.*\)\.o:@$DIR\1.d $DIR\1.o :@"
hooks/post-receive
--
1
0
See <https://jenkins-ci.mcs.anl.gov/job/triton/147/>
------------------------------------------
[...truncated 1533 lines...]
# idx:3 node_id:::3347, virt_id:e8d0:30bc:e88e:55fb:cf83:74c5:c7:27db
# ring 48:
# idx:0 node_id:::3346, virt_id:1ffe:1c79:4a88:5657:16e6:482a:1729:c857
# idx:1 node_id:::3344, virt_id:307d:92a0:403c:6c93:dfb4:d21b:572b:19c1
# idx:2 node_id:::3345, virt_id:31af:e183:a1f9:c4d3:c016:75d1:7357:47d3
# idx:3 node_id:::3347, virt_id:efab:9b9c:c35b:5d5e:bf12:a948:5563:8207
# ring 49:
# idx:0 node_id:::3344, virt_id:5264:be20:239e:6e02:5cc2:b069:ecb5:5ace
# idx:1 node_id:::3347, virt_id:81ad:610a:8e54:290c:4970:6c26:7036:c1d0
# idx:2 node_id:::3346, virt_id:d54e:d730:e4ff:d07:d531:d74:f243:c7c3
# idx:3 node_id:::3345, virt_id:ec30:10d:7cba:2fca:423d:85c3:fefa:4100
# ring 50:
# idx:0 node_id:::3345, virt_id:65ed:3d4:861f:b48a:797c:2013:4a26:4367
# idx:1 node_id:::3346, virt_id:cc43:b9fc:a27d:8ac:7516:2a2e:89e4:b547
# idx:2 node_id:::3347, virt_id:e204:45b8:a05a:ed85:cea2:af09:b171:b43
# idx:3 node_id:::3344, virt_id:fd8d:9383:57da:17ad:5535:63fd:9006:a16
# ring 51:
# idx:0 node_id:::3346, virt_id:3c60:f04b:c1a5:1624:df1:f0c:414c:848c
# idx:1 node_id:::3345, virt_id:609f:b9cc:ee47:1de4:3c0a:afb8:651c:3a41
# idx:2 node_id:::3344, virt_id:86be:c60d:ac2d:ef7e:6ea8:50e8:1790:3069
# idx:3 node_id:::3347, virt_id:fb89:a8d5:f704:34d0:cf74:3206:9bd9:30a1
# ring 52:
# idx:0 node_id:::3345, virt_id:1f25:68e6:479e:19cf:908e:e665:a862:9c89
# idx:1 node_id:::3347, virt_id:4aaf:c2ad:1799:26cb:64a0:d600:b4de:c1d0
# idx:2 node_id:::3344, virt_id:6d48:c159:2585:383d:33ce:e922:6b6:da1
# idx:3 node_id:::3346, virt_id:9662:73fe:5491:63bc:59f0:33ff:4cd3:ce93
# ring 53:
# idx:0 node_id:::3346, virt_id:11b0:1d3:2a3:75a3:8171:fe1f:1996:ce28
# idx:1 node_id:::3347, virt_id:41a1:6f07:3df4:a1b7:f44d:64fe:7769:9b07
# idx:2 node_id:::3344, virt_id:4964:de1d:c1cb:47f0:6222:d154:628d:87f0
# idx:3 node_id:::3345, virt_id:5467:f42b:a5a:6b1a:8b0f:1d49:8cb3:acfc
# ring 54:
# idx:0 node_id:::3344, virt_id:e91:f217:cc4b:4ed6:fbd9:8e4a:14be:dca7
# idx:1 node_id:::3347, virt_id:2b22:2fa2:a699:1bb2:117c:853f:a56:1153
# idx:2 node_id:::3345, virt_id:341d:fb00:ff3:3354:2b80:e7fa:a4ea:fcc8
# idx:3 node_id:::3346, virt_id:43a9:f1d0:df33:6692:2d3a:d612:398a:74a6
# ring 55:
# idx:0 node_id:::3345, virt_id:119:f46a:c040:119f:6256:93bf:c3d5:780e
# idx:1 node_id:::3346, virt_id:680a:6d4e:1934:555c:babe:ad32:b1e8:cf66
# idx:2 node_id:::3347, virt_id:75ad:236:808b:1fc0:e07c:70c7:d2e1:37fb
# idx:3 node_id:::3344, virt_id:fd3f:3ab0:ba81:c874:18a7:1c2a:1f11:cf93
# ring 56:
# idx:0 node_id:::3346, virt_id:1710:f045:e1ba:78db:5ffb:8aa0:341:a980
# idx:1 node_id:::3345, virt_id:1d19:fd1d:808b:93b0:ff92:806e:bc41:3b98
# idx:2 node_id:::3344, virt_id:d4c0:7f2a:1ae:f9e1:2ef8:6225:733e:cede
# idx:3 node_id:::3347, virt_id:fabe:d9e5:3b77:efd9:e03f:6474:1072:35ed
# ring 57:
# idx:0 node_id:::3347, virt_id:197b:605e:83b9:796c:2761:4ac3:5bab:8eb6
# idx:1 node_id:::3346, virt_id:9c57:bb5:5a47:59fd:7829:4368:4c6b:b162
# idx:2 node_id:::3345, virt_id:bdab:2a41:a673:dffc:623e:4893:2bab:6366
# idx:3 node_id:::3344, virt_id:cba8:8ba2:861d:cf70:b120:8d12:b759:6978
# ring 58:
# idx:0 node_id:::3347, virt_id:45d:962f:d7ac:30e9:a39e:65b8:bad7:d44f
# idx:1 node_id:::3345, virt_id:b8f:76c9:6b61:1d6c:109f:42d3:fc83:c9f0
# idx:2 node_id:::3344, virt_id:480a:ef66:5bee:5840:9f73:99e:fc87:8fb9
# idx:3 node_id:::3346, virt_id:97a6:b79a:26e1:69c4:d653:9149:7c56:e018
# ring 59:
# idx:0 node_id:::3347, virt_id:4d76:ba39:79b4:7468:2d66:2171:42a0:8a85
# idx:1 node_id:::3344, virt_id:b639:aa85:8484:39c:5062:66a1:3118:8d74
# idx:2 node_id:::3346, virt_id:d635:e835:ea38:4bba:7a70:30c4:8fe3:22b0
# idx:3 node_id:::3345, virt_id:f85b:1272:b717:5808:e613:333b:cab4:5f73
# ring 60:
# idx:0 node_id:::3347, virt_id:317b:ec62:5380:f924:44ad:a462:215c:b275
# idx:1 node_id:::3344, virt_id:59ed:5124:d223:c50c:ba1:3b68:ded5:218b
# idx:2 node_id:::3346, virt_id:b25c:c1ea:ca66:c61e:f432:b0aa:80bc:9098
# idx:3 node_id:::3345, virt_id:d042:dfbf:4075:964e:e069:6ff5:ee9b:aa2a
# ring 61:
# idx:0 node_id:::3344, virt_id:44b:1132:2609:3639:98e7:4e80:5232:f759
# idx:1 node_id:::3345, virt_id:3c3d:5b99:185f:9ce2:4e7b:18f8:5888:9852
# idx:2 node_id:::3346, virt_id:4dbf:b379:2e38:9246:b60d:b9d3:f36f:8ba5
# idx:3 node_id:::3347, virt_id:bd89:50ec:c081:3346:91b4:ee6b:e5b0:c90a
# ring 62:
# idx:0 node_id:::3347, virt_id:6b5a:cbfb:520e:a2cc:1b36:ee73:7ec2:d998
# idx:1 node_id:::3344, virt_id:8252:7d3e:8a56:f8b:512a:3a4d:7324:92f1
# idx:2 node_id:::3346, virt_id:8bbc:75ce:f5e4:257c:17bb:c2fc:3973:da68
# idx:3 node_id:::3345, virt_id:b7e6:af63:610f:8d71:db91:3aaf:a979:8030
# ring 63:
# idx:0 node_id:::3347, virt_id:15db:fee0:2bb5:8384:d66:411c:a111:f4b0
# idx:1 node_id:::3344, virt_id:9de2:7ce6:c4a8:9139:89bb:412a:c345:f3f7
# idx:2 node_id:::3346, virt_id:cbb3:b315:373a:d8eb:1fb2:f1fb:251e:6c0a
# idx:3 node_id:::3345, virt_id:dcbb:6818:1199:7b87:1011:4bf6:70e4:136f
# oid ::123 mapped to ring 35
# oid ::123 mapped 0 replica to node ::3344
# oid ::123 mapped 1 replica to node ::3347
# oid ::123 mapped 2 replica to node ::3345
PASS: tests/triton-show-placement.sh
enosys example: base:Not implemented
wrapped enosys example: :::stacked msg level 2, :::stacked msg level 1, :::stacked msg level 0, base:Not implemented
PASS: tests/common/test-triton-ret-t
all servers:
::1
::3fff:ffff:ffff:ffff
::7fff:ffff:ffff:ffff
::bfff:ffff:ffff:fffd
closest to OID: ::7fff:ffff:ffff:fffc:
::7fff:ffff:ffff:ffff
::bfff:ffff:ffff:fffd
::1
all servers:
::1
::3fff:ffff:ffff:ffff
::7fff:ffff:ffff:ffff
::bfff:ffff:ffff:fffd
closest to OID: ::bfff:ffff:ffff:fffa:
::bfff:ffff:ffff:fffd
::1
::3fff:ffff:ffff:ffff
PASS: tests/placement/test-placement-1d.sh
all servers:
::1
::3fff:ffff:ffff:ffff
::7fff:ffff:ffff:ffff
::bfff:ffff:ffff:fffd
closest to OID: ::7fff:ffff:ffff:fffc:
::7fff:ffff:ffff:ffff
::bfff:ffff:ffff:fffd
::3fff:ffff:ffff:ffff
all servers:
::1
::3fff:ffff:ffff:ffff
::7fff:ffff:ffff:ffff
::bfff:ffff:ffff:fffd
closest to OID: ::bfff:ffff:ffff:fffa:
::7fff:ffff:ffff:ffff
::3fff:ffff:ffff:ffff
::bfff:ffff:ffff:fffd
PASS: tests/placement/test-placement-mrh.sh
tmpbase: <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-52PsI1>
PASS: tests/common/test-debug.sh
serialized: <::1><testkey><bar>,<::2><testkey><foo>,<::1><testkeyB><foo>,<::2><testkeyB><foo>
node1 testkeyB value: foo
node_list[0]: ::1
node_list[1]: ::2
PASS: tests/system-state/test-system-state
+ '[' -z <https://jenkins-ci.mcs.anl.gov/job/triton/ws/code> ']'
+ source <https://jenkins-ci.mcs.anl.gov/job/triton/ws/code/tests/test-util.sh>
++ '[' -n <https://jenkins-ci.mcs.anl.gov/job/triton/ws/> ']'
++ TMPDIR=<https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp>
++ export TMPDIR
++ mkdir -p <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp>
+++ mktemp --tmpdir -d test-XXXXXX
++ TMPBASE=<https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-4iF8b5>
++ echo 'tmpbase: <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-4iF8b5'>
tmpbase: <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-4iF8b5>
++ '[' '!' -d <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-4iF8b5> ']'
+ test_start_servers 1 5 60 1
+ nservers=1
+ startwait=5
+ maxtime=60s
+ repfactor=1
+ pid=8650
+ startport=3344
++ expr 3344 + 1 - 1
+ endport=3344
+ test_gen_conf
+ echo '# auto-generated configuration file from test pid 8650, 1 servers'
+ echo 'hosts = {'
++ seq 3344 3344
+ for i in '`seq $startport $endport`'
+ echo -e '"::3344 tcp://localhost:3344",'
+ echo '}'
+ echo 'triton_debug_file = <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-4iF8b5/triton-s…'>
+ echo 'triton_tosd_db_path = <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-4iF8b5/triton-s…'>
+ echo 'triton_tosd_data_path = <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-4iF8b5/triton-s…'>
+ echo 'triton_debug_masks = "all"'
+ echo 'triton_tosd_flags = "DATA_SYNC"'
+ [[ 1 -gt 0 ]]
+ echo 'triton_rosd_default_replication_factor = 1'
++ seq 3344 3344
+ for i in '`seq $startport $endport`'
+ '[' 0 -ne 0 ']'
+ sleep 5
+ timeout --signal=9 60s src/server/triton-server --conf <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-4iF8b5/triton-8…> --listenaddr tcp://localhost:3344
+ svr1=tcp://localhost:3344
+ run_to 60 tests/asg/test-asg-simple tcp://localhost:3344 555
+ maxtime=60s
+ shift
+ timeout --signal=9 60s tests/asg/test-asg-simple tcp://localhost:3344 555
+ '[' 0 -ne 0 ']'
+ run_to 60 src/admin-tools/triton-shutdown-all-servers tcp://localhost:3344
+ wait
+ exit 0
PASS: tests/asg/test-asg-simple.sh
+ '[' -z <https://jenkins-ci.mcs.anl.gov/job/triton/ws/code> ']'
+ source <https://jenkins-ci.mcs.anl.gov/job/triton/ws/code/tests/test-util.sh>
++ '[' -n <https://jenkins-ci.mcs.anl.gov/job/triton/ws/> ']'
++ TMPDIR=<https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp>
++ export TMPDIR
++ mkdir -p <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp>
+++ mktemp --tmpdir -d test-XXXXXX
++ TMPBASE=<https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-eQEPkE>
++ echo 'tmpbase: <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-eQEPkE'>
tmpbase: <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-eQEPkE>
++ '[' '!' -d <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-eQEPkE> ']'
+ test_start_servers 1 5 60 1
+ nservers=1
+ startwait=5
+ maxtime=60s
+ repfactor=1
+ pid=9348
+ startport=3344
++ expr 3344 + 1 - 1
+ endport=3344
+ test_gen_conf
+ echo '# auto-generated configuration file from test pid 9348, 1 servers'
+ echo 'hosts = {'
++ seq 3344 3344
+ for i in '`seq $startport $endport`'
+ echo -e '"::3344 tcp://localhost:3344",'
+ echo '}'
+ echo 'triton_debug_file = <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-eQEPkE/triton-s…'>
+ echo 'triton_tosd_db_path = <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-eQEPkE/triton-s…'>
+ echo 'triton_tosd_data_path = <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-eQEPkE/triton-s…'>
+ echo 'triton_debug_masks = "all"'
+ echo 'triton_tosd_flags = "DATA_SYNC"'
+ [[ 1 -gt 0 ]]
+ echo 'triton_rosd_default_replication_factor = 1'
++ seq 3344 3344
+ for i in '`seq $startport $endport`'
+ '[' 0 -ne 0 ']'
+ sleep 5
+ timeout --signal=9 60s src/server/triton-server --conf <https://jenkins-ci.mcs.anl.gov/job/triton/ws/tritontmp/test-eQEPkE/triton-9…> --listenaddr tcp://localhost:3344
+ svr1=tcp://localhost:3344
+ run_to 60 tests/asg/test-asg-multi-init tcp://localhost:3344
+ maxtime=60s
+ shift
+ timeout --signal=9 60s tests/asg/test-asg-multi-init tcp://localhost:3344
+ '[' 0 -ne 0 ']'
+ run_to 60 src/admin-tools/triton-shutdown-all-servers tcp://localhost:3344
+ wait
+ exit 0
PASS: tests/asg/test-asg-multi-init.sh
==================================================================
1 of 23 tests failed
Please report to http://trac.mcs.anl.gov/projects/triton/newticket
==================================================================
make[2]: *** [check-TESTS] Error 1
make[2]: Leaving directory `<https://jenkins-ci.mcs.anl.gov/job/triton/ws/build/tritonbuild'>
make[1]: *** [check-am] Error 2
make[1]: Leaving directory `<https://jenkins-ci.mcs.anl.gov/job/triton/ws/build/tritonbuild'>
make: *** [check] Error 2
Build step 'Execute shell' marked build as failure
TAP Reports Processing: START
Looking for TAP results report in workspace using pattern: build/tritonbuild/tests/results.tap
Did not find any matching files.
1
1
branch, asg-header-cleanup, updated. 90bd88cdf43f5511b7fe1ccf8747af55fdfa016d
by noreply@mcs.anl.gov 16 Jan '15
by noreply@mcs.anl.gov 16 Jan '15
16 Jan '15
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, asg-header-cleanup has been updated
via 90bd88cdf43f5511b7fe1ccf8747af55fdfa016d (commit)
from 9ff998cfe3204c14fa558d17f3934648275b8245 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 90bd88cdf43f5511b7fe1ccf8747af55fdfa016d
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Fri Jan 16 12:13:56 2015 -0500
revert asg_write() argument order change
-----------------------------------------------------------------------
Summary of changes:
code/include/asg.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
Diff of changes:
diff --git a/code/include/asg.h b/code/include/asg.h
index 7f344fe..754b061 100644
--- a/code/include/asg.h
+++ b/code/include/asg.h
@@ -400,9 +400,9 @@ int asg_write (
asg_size_t record_length,
asg_flags_t flags,
asg_update_id_t update_id_condition,
+ asg_update_id_t * new_update_id,
const void * buf,
- asg_size_t * records_written,
- asg_update_id_t * new_update_id);
+ asg_size_t * records_written);
/**
* Punch is exactly like write but writes zero length records.
hooks/post-receive
--
1
0