Commit 569a58e2 authored by Éric Thiébaut's avatar Éric Thiébaut
Browse files

Simplify sending of commands

parent 21fceea8
......@@ -266,18 +266,14 @@ tao_status tao_remote_mirror_set_reference(
double* dest = remote_mirror_get_refs(obj);
// Wait until server be ready for a new command.
int locked;
tao_status status = tao_remote_object_lock_for_command(
&locked, tao_remote_object_cast(obj), secs);
// Copy reference commands.
tao_remote_object_cast(obj), TAO_COMMAND_NONE, secs);
if (status == TAO_OK) {
// Copy reference commands and unlock ressources.
memcpy(dest, vals, nvals*sizeof(double));
}
// Unlock ressources and return final status.
if (locked && tao_remote_mirror_unlock(obj) != TAO_OK) {
status = TAO_ERROR;
if (tao_remote_mirror_unlock(obj) != TAO_OK) {
status = TAO_ERROR;
}
}
return status;
}
......@@ -304,38 +300,24 @@ tao_status tao_remote_mirror_send_commands(
double* dest = remote_mirror_get_req_cmds(obj);
// Wait until server ready for a new command.
int locked;
tao_status status = tao_remote_object_lock_for_command(
&locked, tao_remote_object_cast(obj), secs);
// Get next serial number.
tao_status status = tao_remote_object_lock_for_command(
tao_remote_object_cast(obj), TAO_COMMAND_SEND, secs);
if (status == TAO_OK) {
// Server was ready for the new command. Get next serial number, copy
// actuators values, and unlock object.
tao_serial next = obj->base.serial + 1;
if (next < 1) {
next = 0;
tao_store_error(__func__, TAO_CORRUPTED);
status = TAO_ERROR;
}
if (serial != NULL) {
*serial = next;
}
}
// Copy commands, assign command, notify others.
if (status == TAO_OK) {
memcpy(dest, vals, nvals*sizeof(double));
obj->mark = mark;
obj->base.command = TAO_COMMAND_SEND;
if (tao_remote_mirror_broadcast_condition(obj) != TAO_OK) {
obj->base.command = TAO_COMMAND_NONE;
if (tao_remote_mirror_unlock(obj) != TAO_OK) {
status = TAO_ERROR;
}
}
// Unlock ressources and return final status.
if (locked && tao_remote_mirror_unlock(obj) != TAO_OK) {
status = TAO_ERROR;
}
return status;
}
......
......@@ -234,54 +234,85 @@ error:
}
tao_status tao_remote_object_lock_for_command(
int* locked,
tao_remote_object* obj,
tao_command command,
double secs)
{
// Minimal check.
if (obj == NULL || locked == NULL) {
if (obj == NULL) {
tao_store_error(__func__, TAO_BAD_ADDRESS);
if (locked != NULL) {
*locked = false;
}
return TAO_ERROR;
}
// Convert seconds to absolute time, then lock resources and wait until
// the server be ready for a new command.
// Convert seconds to absolute time, then lock resources and wait until the
// server is ready for a new command, killed, or some error occurs.
tao_status status;
tao_time abstime;
bool locked;
switch (tao_get_absolute_timeout(&abstime, secs)) {
case TAO_TIMEOUT_NEVER:
status = tao_remote_object_lock(obj);
*locked = (status == TAO_OK);
locked = (status == TAO_OK);
while (wait_for_command(status, obj)) {
status = tao_remote_object_wait_condition(obj);
}
break;
case TAO_TIMEOUT_FUTURE:
status = tao_remote_object_abstimed_lock(obj, &abstime);
*locked = (status == TAO_OK);
locked = (status == TAO_OK);
while (wait_for_command(status, obj)) {
status = tao_remote_object_abstimed_wait_condition(obj, &abstime);
}
break;
case TAO_TIMEOUT_NOW:
status = tao_remote_object_try_lock(obj);
*locked = (status == TAO_OK);
locked = (status == TAO_OK);
if (wait_for_command(status, obj)) {
status = TAO_TIMEOUT;
}
break;
case TAO_TIMEOUT_PAST:
*locked = false;
locked = false;
status = TAO_TIMEOUT;
break;
default: // TAO_TIMEOUT_ERROR
*locked = false;
locked = false;
status = TAO_ERROR;
break;
}
if (status == TAO_OK) {
// Server is either killed or idle.
if (obj->state == TAO_STATE_KILLED) {
// Server has been killed.
if (command != TAO_COMMAND_KILL) {
#if TAO_ASSUME_TIMOUT_IF_SERVER_KILLED
status = TAO_TIMEOUT;
#else
tao_store_error(func, TAO_NOT_RUNNING);
status = TAO_ERROR;
#endif
}
} else if (obj->command == TAO_COMMAND_NONE) {
// Server is ready to accept a new command.
if (command != TAO_COMMAND_NONE) {
obj->command = command;
if (tao_remote_object_broadcast_condition(obj) != TAO_OK) {
obj->command = TAO_COMMAND_NONE;
status = TAO_ERROR;
}
}
} else {
// Unexpected result.
tao_store_error(__func__, TAO_ASSERTION_FAILED);
status = TAO_ERROR;
}
}
// In case of error, if object has been locked, unlock it.
if (status != TAO_OK && locked && tao_remote_object_unlock(obj) != TAO_OK) {
status = TAO_ERROR;
}
return status;
}
......@@ -301,18 +332,13 @@ tao_status tao_remote_object_send_simple_command(
return TAO_OK;
}
}
int locked;
tao_status status = tao_remote_object_lock_for_command(&locked, obj, secs);
tao_status status = tao_remote_object_lock_for_command(obj, command, secs);
if (status == TAO_OK) {
obj->command = command;
if (tao_remote_object_broadcast_condition(obj) != TAO_OK) {
obj->command = TAO_COMMAND_NONE;
// Command is about to be sent, nothing else to do than unlock.
if (tao_remote_object_unlock(obj) != TAO_OK) {
status = TAO_ERROR;
}
}
if (locked && tao_remote_object_unlock(obj) != TAO_OK) {
status = TAO_ERROR;
}
if (command == TAO_COMMAND_KILL) {
// Assume success upon timout if the server is no longer alive.
if (status == TAO_TIMEOUT && !is_alive(obj)) {
......
......@@ -17,6 +17,14 @@
TAO_BEGIN_DECLS
/**
* Report command timeout when server killed?
*
* This macros specifies whether a timeout result is returned
* when a command failed because the server has been killed.
*/
#define TAO_ASSUME_TIMOUT_IF_SERVER_KILLED 1
/**
* Remote object struture.
*
......
......@@ -346,30 +346,32 @@ extern tao_status tao_remote_object_kill(
* Wait for a remote server to be ready for a new command.
*
* This function attempts to lock a remote shared object and to wait for its
* server to accept commands or to be killed. On return, `*locked` indicates
* whether the remote object has been locked by the caller. It the returned
* status is `TAO_OK`, the lock has been acquired and the server shall be
* either idle or killed.
* server to accept commands or to be killed. Upon success, the next command
* to execute is set to be @b cmd and, unless the command is @ref
* TAO_COMMAND_NONE, the server is notified that a new command is pending. The
* command will be executed just after the object is unlocked. This behavior
* is intended for commands that require other arguments than just the the
* command itself.
*
* @warning The object must be initially unlocked and it is the caller's
* responsibility to eventually unlock the object if `*locked` is
* true.
* responsibility to eventually unlock the object if `TAO_OK` is
* returned by this function.
*
* @note This is a low level function provided to implement sending of commands
* for various remote object types.
*
* @param locked Address to store whether the object has been locked.
*
* @param obj Pointer to a shared object connected to a remote server.
*
* @param cmd Command to send.
*
* @param secs Maximum amount of time to wait (in seconds).
*
* @return @ref TAO_OK on success; @ref TAO_ERROR on failure; @ref TAO_TIMEOUT
* if the time limits expired.
*/
extern tao_status tao_remote_object_lock_for_command(
int* locked,
tao_remote_object* obj,
tao_command cmd,
double secs);
extern tao_remote_object* tao_remote_object_attach(
......
......@@ -43,7 +43,7 @@ TAO_BEGIN_DECLS
*
* Shared cameras are read/write locked objects (see @ref tao_rwlocked_object)
* used to communicate with camera servers in TAO.
*
* @see tao_shared_camera_.
*/
typedef struct tao_shared_camera_ tao_shared_camera;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment