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 9711f73ce9cd19e619578ce99e36e8adaeab1b63 (commit)
via 1ca0d79ad116ec3f89b608cb91c26a16dd41f4df (commit)
via d2dff7c9ab1a95208a6967f0e8baef46bb795ea0 (commit)
via 5842c5bfd6dc0bca03687adfa40b2aca6bb6b405 (commit)
via faefc6bb3460de0d7aff46d12517510cae19b9d8 (commit)
from 14c01f63a7e70702da6f9878f0badf9cefc54a52 (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 9711f73ce9cd19e619578ce99e36e8adaeab1b63
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Mon Sep 30 16:04:35 2013 -0400
non-replicated touch in test case for now
commit 1ca0d79ad116ec3f89b608cb91c26a16dd41f4df
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Mon Sep 30 15:56:29 2013 -0400
rosd bug fixes
commit d2dff7c9ab1a95208a6967f0e8baef46bb795ea0
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Mon Sep 30 15:44:51 2013 -0400
adjust s2s create handling
commit 5842c5bfd6dc0bca03687adfa40b2aca6bb6b405
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Mon Sep 30 15:19:47 2013 -0400
fill in rosd_create() path, doesn't work yet
commit faefc6bb3460de0d7aff46d12517510cae19b9d8
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Mon Sep 30 14:50:40 2013 -0400
port over some code from old rosd.aer
error handling and partial create logic
-----------------------------------------------------------------------
Summary of changes:
code/sandbox/replicated-osd/rosd.aer | 3 +
code/src/admin-tools/triton-touch.ae | 17 +-
code/src/replicated-osd/rosd.ae | 451 ++++++++++++++++++++++++++++++++--
code/src/replicated-osd/rosd.hae | 14 +
code/tests/triton-touch.sh.in | 2 +-
5 files changed, 463 insertions(+), 24 deletions(-)
Diff of changes:
diff --git a/code/sandbox/replicated-osd/rosd.aer b/code/sandbox/replicated-osd/rosd.aer
index 6726384..06d82af 100644
--- a/code/sandbox/replicated-osd/rosd.aer
+++ b/code/sandbox/replicated-osd/rosd.aer
@@ -588,7 +588,10 @@ static __blocking triton_ret_t rosd_create_do_work(
triton_uint128_to_string(oid_str, TRITON_UINT128_STRLEN, oid);
triton_debug(rosd_dbg_mask, "ROSD local create of oid %s on %d'th server.\n", oid_str, my_position);
/* perform local operation */
+ /* TODO: fill this in */
+#if 0
local_tret = rosd_create_local_storage(oid, replication_factor, niid);
+#endif
}
}
diff --git a/code/src/admin-tools/triton-touch.ae b/code/src/admin-tools/triton-touch.ae
index 0c6b5b3..4259a70 100644
--- a/code/src/admin-tools/triton-touch.ae
+++ b/code/src/admin-tools/triton-touch.ae
@@ -18,11 +18,13 @@ __blocking int aesop_main(int argc, char **argv)
triton_ret_t tret;
char* svr_string;
uint128_t oid;
+ unsigned int replication_factor;
+ int ret;
- if(argc != 3)
+ if(argc != 4)
{
- fprintf(stderr, "Usage: %s <server> <oid>\n", argv[0]);
- fprintf(stderr, " Example: triton-touch tcp://localhost:3344 123.123\n");
+ fprintf(stderr, "Usage: %s <server> <oid> <replication_factor>\n", argv[0]);
+ fprintf(stderr, " Example: triton-touch tcp://localhost:3344 123.123 3\n");
return(-1);
}
@@ -39,6 +41,12 @@ __blocking int aesop_main(int argc, char **argv)
return(-1);
}
+ ret = sscanf(argv[3], "%u", &replication_factor);
+ if(ret != 1)
+ {
+ fprintf(stderr, "Error: %s is an invalid replication factor.\n", argv[3]);
+ }
+
tret = triton_debug_init();
if(triton_is_error(tret))
{
@@ -70,8 +78,7 @@ __blocking int aesop_main(int argc, char **argv)
}
/* create object */
- /* TODO: make replication factor configurable */
- tret = remote_triton_rpc_rosd_create(oid, 3, 0);
+ tret = remote_triton_rpc_rosd_create(oid, replication_factor, 0);
if(triton_is_error(tret))
{
triton_error_print(tret, "remote_triton_rpc_rosd_create()");
diff --git a/code/src/replicated-osd/rosd.ae b/code/src/replicated-osd/rosd.ae
index 3a7e304..da4f204 100644
--- a/code/src/replicated-osd/rosd.ae
+++ b/code/src/replicated-osd/rosd.ae
@@ -14,15 +14,48 @@
#include "src/remote/mercury-engine.hae"
#include "src/remote/mercury-encode.h"
#include "src/system-state/system-state.hae"
+#include "src/transactional-osd/transactional-osd.hae"
+
+/* TODO: need a way to configure and/or reserve these values */
+/* default replication level for objects */
+static int default_replication = 3;
+/* default fork used to store replication factor in object */
+#define REP_FACTOR_FORK UINT64_MAX
+
/* generate input and output structs */
MERCURY_GEN_PROC(triton_rpc_rosd_create_out_t, ((triton_ret_t)(tret)))
-MERCURY_GEN_PROC(triton_rpc_rosd_create_in_t, ((uint128_t)(oid))((uint32_t)(flags))((uint32_t)(replication_factor))((uint64_t)(niid)))
+MERCURY_GEN_PROC(triton_rpc_rosd_create_in_t, ((uint128_t)(oid))((uint32_t)(flags))((uint32_t)(expected_position))((uint32_t)(replication_factor))((uint64_t)(niid)))
static hg_id_t g_rpc_rosd_create_id;
static int triton_rpc_rosd_create_handler(hg_handle_t handle);
static triton_ret_t triton_oid_to_addrs(uint128_t oid,
uint32_t replication_factor, int* my_position, na_addr_t *addr_array);
+static __blocking triton_ret_t rosd_create_do_work(
+ uint128_t oid,
+ uint32_t flags,
+ uint32_t replication_factor,
+ int my_position,
+ na_addr_t next_addr,
+ uint64_t niid,
+ int from_client_flag);
+static __blocking triton_ret_t interpret_errors(
+ triton_ret_t local_error_code,
+ triton_ret_t remote_error_code,
+ int my_position,
+ int(*usage_error_check)(triton_ret_t tret),
+ int from_client_flag);
+static __blocking triton_ret_t interpret_error(
+ triton_ret_t local_error_code,
+ int my_position,
+ int(*usage_error_check)(triton_ret_t tret),
+ int from_client_flag);
+static int is_usage_error_create(triton_ret_t tret);
+static __blocking void trigger_server_fault(triton_ret_t tret);
+static __blocking triton_ret_t rosd_create_local_storage(
+ uint128_t oid,
+ uint32_t replication_factor,
+ uint64_t niid);
static __blocking triton_ret_t triton_rpc_rosd_create(hg_handle_t handle)
{
@@ -30,6 +63,11 @@ static __blocking triton_ret_t triton_rpc_rosd_create(hg_handle_t handle)
triton_rpc_rosd_create_in_t in;
int ret = 0;
char oid_str[TRITON_UINT128_STRLEN];
+ int my_position;
+ na_addr_t *addr_array = NULL;
+ int got_addrs = 0;
+ int i;
+ na_addr_t next_addr;
triton_debug(triton_dbg_rosd, "Called triton_rpc_rosd_create()\n");
@@ -48,11 +86,36 @@ static __blocking triton_ret_t triton_rpc_rosd_create(hg_handle_t handle)
oid_str, in.flags, in.replication_factor, llu(in.niid));
- /* TODO: implement real work here; this is just a skeleton */
+ /* map oid to server addresses */
+ addr_array = malloc(in.replication_factor*sizeof(*addr_array));
+ if(!addr_array)
+ {
+ out.tret = TRITON_ERR_NOMEM;
+ }
+ if(!triton_is_error(out.tret))
+ {
+ out.tret = triton_oid_to_addrs(in.oid, in.replication_factor, &my_position,
+ addr_array);
+ if(!triton_is_error(out.tret))
+ got_addrs = 1;
+ }
- /* Fill output structure */
- out.tret = TRITON_SUCCESS;
-
+ if(!triton_is_error(out.tret))
+ {
+ /* check position in chain */
+ if(my_position != in.expected_position)
+ {
+ out.tret = TRITON_ERR_WRONG_SERVER;
+ }
+ }
+ if(my_position < (in.replication_factor-1))
+ {
+ next_addr = addr_array[my_position+1];
+ }
+
+ out.tret = rosd_create_do_work(in.oid, in.flags, in.replication_factor,
+ my_position, next_addr, in.niid, 1);
+
/* Free handle and send response back */
ret = HG_Handler_start_output(handle, &out);
if (ret != HG_SUCCESS)
@@ -62,6 +125,11 @@ static __blocking triton_ret_t triton_rpc_rosd_create(hg_handle_t handle)
assert(0);
}
+ for(i=0; i<in.replication_factor && got_addrs; i++)
+ triton_mercury_addr_free(&addr_array[i]);
+ if(addr_array)
+ free(addr_array);
+
return(TRITON_SUCCESS);
}
@@ -118,6 +186,7 @@ static triton_ret_t triton_oid_to_addrs(uint128_t oid, uint32_t replication_fact
triton_node_t* target_nodes;
int i;
triton_node_t self;
+ char oid_str[TRITON_UINT128_STRLEN];
*my_position = -1;
@@ -149,6 +218,8 @@ static triton_ret_t triton_oid_to_addrs(uint128_t oid, uint32_t replication_fact
return(tret);
}
+ triton_uint128_to_string(oid_str, TRITON_UINT128_STRLEN, oid);
+
for(i=0; i<replication_factor; i++)
{
if(triton_node_equal(self, target_nodes[i]))
@@ -161,6 +232,8 @@ static triton_ret_t triton_oid_to_addrs(uint128_t oid, uint32_t replication_fact
free(node_array);
return(TRITON_ERR_UNKNOWN);
}
+
+ triton_debug(triton_dbg_rosd, "triton_oid_to_addrs() mapped oid %s to server %d: %s\n", oid_str, i, svr_string);
tret = triton_mercury_addr_lookup(svr_string, &addr_array[i]);
if(triton_is_error(tret))
@@ -170,48 +243,43 @@ static triton_ret_t triton_oid_to_addrs(uint128_t oid, uint32_t replication_fact
free(svr_string);
return(tret);
}
+
+ free(svr_string);
}
free(target_nodes);
free(node_array);
- free(svr_string);
return(TRITON_SUCCESS);
}
-__blocking triton_ret_t remote_triton_rpc_rosd_create(
+__blocking triton_ret_t __remote_triton_rpc_rosd_create(
+ na_addr_t addr,
uint128_t oid,
uint32_t replicas,
- uint32_t flags)
+ uint32_t flags,
+ uint32_t expected_position)
{
triton_rpc_rosd_create_out_t out;
triton_rpc_rosd_create_in_t in;
hg_request_t request;
int ret;
triton_ret_t tret;
- na_addr_t addr;
int position;
- /* we contact the first server (master) for oid */
- tret = triton_oid_to_addrs(oid, 1, &position, &addr);
- if(triton_is_error(tret))
- {
- return(tret);
- }
-
in.oid = oid;
in.flags = flags;
in.replication_factor = replicas;
/* TODO: generate real NIIDs */
in.niid = 0;
+ in.expected_position = expected_position;
ret = HG_Forward(addr, g_rpc_rosd_create_id, &in,
&out, &request);
if(ret != HG_SUCCESS)
{
triton_error_msg("HG_Forward() failure.\n");
- triton_mercury_addr_free(addr);
return(TRITON_ERR_UNKNOWN);
}
@@ -219,18 +287,365 @@ __blocking triton_ret_t remote_triton_rpc_rosd_create(
if(triton_is_error(tret))
{
HG_Request_free(request);
- triton_mercury_addr_free(addr);
return(tret);
}
tret = triton_error_dup(out.tret);
HG_Request_free(request);
+
+ return(tret);
+}
+
+__blocking triton_ret_t remote_triton_rpc_rosd_create(
+ uint128_t oid,
+ uint32_t replicas,
+ uint32_t flags)
+{
+ triton_ret_t tret;
+ na_addr_t addr;
+ int position;
+
+ /* we contact the first server (master) for oid */
+ tret = triton_oid_to_addrs(oid, 1, &position, &addr);
+ if(triton_is_error(tret))
+ {
+ return(tret);
+ }
+
+ tret = __remote_triton_rpc_rosd_create(addr, oid, replicas, flags, 0);
+
triton_mercury_addr_free(addr);
return(tret);
}
+static __blocking triton_ret_t rosd_create_do_work(
+ uint128_t oid,
+ uint32_t flags,
+ uint32_t replication_factor,
+ int my_position,
+ na_addr_t next_addr,
+ uint64_t niid,
+ int from_client_flag)
+{
+ triton_ret_t local_tret;
+ triton_ret_t remote_tret = TRITON_SUCCESS;
+ triton_ret_t tret;
+
+ /* right now only chained replication is supported */
+ assert(!(flags & ROSD_FLAG_FANOUT));
+ flags |= ROSD_FLAG_CHAIN;
+
+ /* forward request while simultaneously performing local work */
+ pwait
+ {
+ pprivate char oid_str[TRITON_UINT128_STRLEN];
+ pbranch
+ {
+ if(my_position < replication_factor -1)
+ {
+ triton_uint128_to_string(oid_str, TRITON_UINT128_STRLEN, oid);
+ triton_debug(triton_dbg_rosd,
+ "ROSD forwarding create of oid %s to %d'th server.\n",
+ oid_str, my_position+1);
+
+ remote_tret = __remote_triton_rpc_rosd_create(next_addr, oid,
+ replication_factor,
+ flags, my_position+1);
+ }
+ }
+ pbranch
+ {
+ triton_uint128_to_string(oid_str, TRITON_UINT128_STRLEN, oid);
+ triton_debug(triton_dbg_rosd, "ROSD local create of oid %s on %d'th server.\n", oid_str, my_position);
+ /* perform local operation */
+ local_tret = rosd_create_local_storage(oid, replication_factor, niid);
+ }
+ }
+
+ if(my_position < replication_factor -1)
+ tret = interpret_errors(local_tret, remote_tret, my_position,
+ is_usage_error_create, from_client_flag);
+ else
+ tret = interpret_error(local_tret, my_position, is_usage_error_create,
+ from_client_flag);
+
+ return(tret);
+}
+
+/**
+ * Compares the error code from local operations with forwarded operations
+ * to determine what action the server should take (if any) and what error
+ * code to propagate to the remote caller
+ *
+ * NOTE: in most cases we trust the recovery process to sort out
+ * discrepancies between servers following a fault. The main purpose of
+ * this function is not to clean up, but to determine how to represent
+ * various cases to clients, and when to explicitly fail servers.
+ */
+static __blocking triton_ret_t interpret_errors(
+ triton_ret_t local_error_code,
+ triton_ret_t remote_error_code,
+ int my_position,
+ int(*usage_error_check)(triton_ret_t tret),
+ int from_client_flag)
+{
+ triton_ret_t final_error_code = TRITON_SUCCESS;
+
+ /* do the remote and local return codes match? */
+ if(triton_error_equal(local_error_code, remote_error_code))
+ {
+ /* are both successful or the result of a usage error? */
+ if(triton_error_equal(local_error_code, TRITON_SUCCESS) ||
+ usage_error_check(local_error_code))
+ {
+ /* Nothing unusual; just propagate */
+ triton_error_destroy(remote_error_code);
+ return(local_error_code);
+ }
+ }
+
+ /* is the remote server saying to try again? */
+ if(triton_error_equal(remote_error_code, TRITON_ERR_AGAIN))
+ {
+ /* if we already know there was a usage error, then we can return
+ * that
+ */
+ if(usage_error_check(local_error_code))
+ {
+ /* Nothing unusual; just propagate */
+ triton_error_destroy(remote_error_code);
+ return(local_error_code);
+ }
+ else
+ {
+ /* otherwise we need to push the ERR_AGAIN all the way back to
+ * the client so that it can restart the operation.
+ */
+ triton_error_destroy(local_error_code);
+ return(remote_error_code);
+ }
+ }
+
+ /* The trickiest case is when there is a usage error in one return
+ * code but success in the other. This implies some state skew in the
+ * system or a software bug. The recovery process won't help here; we
+ * need to request some administrative action. We also can't fail any
+ * servers because we don't know which one is "right".
+ */
+ if(triton_error_equal(local_error_code, TRITON_SUCCESS) &&
+ usage_error_check(remote_error_code))
+ {
+ triton_error_msg_ret(remote_error_code, "Received remote error code that isn't consistent with local (successful) error code. Requesting FSCK.");
+ triton_error_destroy(remote_error_code);
+ return(TRITON_ERR_FSCK);
+ }
+ if(triton_error_equal(remote_error_code, TRITON_SUCCESS) &&
+ usage_error_check(local_error_code))
+ {
+ triton_error_msg_ret(local_error_code, "Received remote error code (success) that isn't consistent with local error code. Requesting FSCK.");
+ triton_error_destroy(local_error_code);
+ return(TRITON_ERR_FSCK);
+ }
+
+ /* if we fall through to this point, then either us or a downstream
+ * server must have encountered a fault of some sort
+ */
+ assert(!usage_error_check(local_error_code) ||
+ !usage_error_check(remote_error_code));
+
+ /* if the error came from this node, and was not a retryable problem,
+ * then trigger a fault here
+ */
+ if(local_error_code != TRITON_SUCCESS &&
+ local_error_code != TRITON_ERR_WRONG_SERVER &&
+ local_error_code != TRITON_ERR_AGAIN)
+ {
+ trigger_server_fault(local_error_code);
+ }
+
+ /* local errors take priority when we are picking which to return */
+ if(local_error_code != TRITON_SUCCESS)
+ final_error_code = local_error_code;
+ else
+ final_error_code = remote_error_code;
+
+ /* if we are the master server for this operation, then we need to ask
+ * clients to remap and try the operation again.
+ */
+ if(from_client_flag)
+ {
+ triton_error_msg_ret(final_error_code, "Asking client to retry operation after remap.");
+ return(TRITON_ERR_WRONG_SERVER);
+ }
+
+ /* if we are talking to another server, then we just preserve the
+ * error code and propagate it.
+ */
+ triton_error_msg_ret(final_error_code, "Propigating error code.");
+ return(final_error_code);
+}
+
+/**
+ * Interprets the error code resulting from a local operation when there is
+ * no forwarded operation, and determines what the final response from the
+ * server should be and if it needs to take any additional action.
+ */
+static __blocking triton_ret_t interpret_error(
+ triton_ret_t local_error_code,
+ int my_position,
+ int(*usage_error_check)(triton_ret_t tret),
+ int from_client_flag)
+{
+ if(triton_error_equal(local_error_code, TRITON_SUCCESS) ||
+ usage_error_check(local_error_code) ||
+ triton_error_equal(local_error_code, TRITON_ERR_WRONG_SERVER) ||
+ triton_error_equal(local_error_code, TRITON_ERR_AGAIN))
+ {
+ /* the operation was successful, encountered a "normal" usage error,
+ * or the server is functioning fine and we just need the client to
+ * try again. Just return the error code as is.
+ */
+ return(local_error_code);
+ }
+
+ /* if we fall through to here, then the local server experienced a fault */
+ trigger_server_fault(local_error_code);
+
+ /* if we are the master server for this operation, then we need to ask
+ * clients to remap and try the operation again.
+ */
+ if(from_client_flag)
+ {
+ triton_error_msg_ret(local_error_code, "Asking client to retry operation after remap.");
+ return(TRITON_ERR_WRONG_SERVER);
+ }
+
+ /* if we are talking to another server, then we just preserve the
+ * error code and propagate it.
+ */
+ triton_error_msg_ret(local_error_code, "Propigating error code.");
+ return(local_error_code);
+}
+
+/**
+ * Checks the triton_ret_t to determine if the error code represents a
+ * usage error rather than an a storage fault. Returns 1 if usage
+ * error code, 0 if storage fault.
+ */
+static int is_usage_error_create(triton_ret_t tret)
+{
+ /* these are the scenarios that a create could fail because of a
+ * usage (ie, semantic) error rather than because of a system fault.
+ */
+ if(triton_error_equal(tret, TRITON_ERR_NO_SERVERS) ||
+ triton_error_equal(tret, TRITON_ERR_EXIST) ||
+ triton_error_equal(tret, TRITON_ERR_ACCES))
+ {
+ /* if there aren't enough servers to satisfy the replication
+ * request, or if the object in question already exists, or if
+ * permission was denied.
+ */
+ return(1);
+ }
+
+ return(0);
+}
+
+/**
+ * Makes a best effort to initiate a failure condition for the specified
+ * server (may be a remote server or the local server itself). This is used
+ * to take a server out of service if we detect a non-recoverable fault.
+ *
+ * \return void
+ */
+/* TODO: write this function */
+static __blocking void trigger_server_fault(triton_ret_t tret)
+{
+ triton_node_t self;
+ char* self_str;
+
+ self = triton_self_node();
+
+ self_str = triton_node_to_string(self);
+
+ triton_error_print(tret, "Server %s shutting down after encountering critical error", self_str);
+
+ free(self_str);
+
+ assert(0);
+ return;
+}
+
+/* rosd_create_local_storage()
+ *
+ * performs the local steps needed in a replicated create
+ */
+static __blocking triton_ret_t rosd_create_local_storage(
+ uint128_t oid,
+ uint32_t replication_factor,
+ uint64_t niid
+)
+{
+ 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 = 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");
+ }
+
+ if(replication_factor != default_replication)
+ {
+
+ /* 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.
+ */
+ 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.
+ */
+ tret_tmp = tosd_remove(oid, 0);
+ if(tret_tmp != TRITON_SUCCESS)
+ {
+ triton_error_destroy(tret_tmp);
+ }
+ /* 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);
+}
+
+
/*
* Local Variables:
* c-basic-offset: 4
diff --git a/code/src/replicated-osd/rosd.hae b/code/src/replicated-osd/rosd.hae
index 18320a1..e405d1c 100644
--- a/code/src/replicated-osd/rosd.hae
+++ b/code/src/replicated-osd/rosd.hae
@@ -7,6 +7,20 @@
#include <triton-uint128.h>
#include "src/common/triton-error.h"
+/* for requests that should be fanned out from the master for replication */
+#define ROSD_FLAG_FANOUT 1
+/* for requests that should be chained from the master for replication */
+#define ROSD_FLAG_CHAIN 2
+/* to make writes automatically truncate any previous data in the object */
+#define ROSD_FLAG_TRUNC_WRITE 4
+/* to make writes conditional (provided version number must be strictly
+ * greater than current version number for the region in the object)
+ */
+#define ROSD_FLAG_COND_WRITE 8
+/* used when forwarding operations from one server to another */
+#define ROSD_FLAG_S2S 16
+
+
void triton_rpc_rosd_register(void);
__blocking triton_ret_t remote_triton_rpc_rosd_create(
diff --git a/code/tests/triton-touch.sh.in b/code/tests/triton-touch.sh.in
index b375c39..7dc46b2 100755
--- a/code/tests/triton-touch.sh.in
+++ b/code/tests/triton-touch.sh.in
@@ -10,7 +10,7 @@ fi
# actual test case
#####################
-src/admin-tools/triton-touch $svr1 1.1
+src/admin-tools/triton-touch $svr1 1.1 1
if [ $? -ne 0 ]; then
src/admin-tools/triton-shutdown-all-servers $svr1 &> /dev/null
exit 1
hooks/post-receive
--