Midas RPC Functions (rpc_xxx)
[The midas.h & midas.c]


Functions

INT rpc_register_client (const char *name, RPC_LIST *list)
INT rpc_register_functions (const RPC_LIST *new_list, INT(*func)(INT, void **))
INT rpc_set_option (HNDLE hConn, INT item, INT value)
INT rpc_send_event (INT buffer_handle, void *source, INT buf_size, INT async_flag, INT mode)
INT rpc_flush_event ()


Function Documentation

INT rpc_flush_event (  ) 

Send event residing in the TCP cache buffer filled by rpc_send_event. This routine should be called when a run is stopped.

Returns:
RPC_SUCCESS, RPC_NET_ERROR

Definition at line 10275 of file midas.c.

Referenced by scan_fragment(), send_event(), and tr_stop().

10276 {
10277    INT i;
10278 
10279    if (!rpc_is_remote())
10280       return RPC_SUCCESS;
10281 
10282    /* return if rpc_send_event was not called */
10283    if (!_tcp_buffer || _tcp_wp == 0)
10284       return RPC_SUCCESS;
10285 
10286    /* empty TCP buffer */
10287    if (_tcp_wp > 0) {
10288       i = send_tcp(_rpc_sock, _tcp_buffer + _tcp_rp, _tcp_wp - _tcp_rp, 0);
10289 
10290       if (i != _tcp_wp - _tcp_rp) {
10291          cm_msg(MERROR, "rpc_flush_event", "send_tcp() failed");
10292          return RPC_NET_ERROR;
10293       }
10294    }
10295 
10296    _tcp_rp = _tcp_wp = 0;
10297 
10298    return RPC_SUCCESS;
10299 }

INT rpc_register_client ( const char *  name,
RPC_LIST *  list 
)

Register RPC client for standalone mode (without standard midas server)

Parameters:
list Array of RPC_LIST structures containing function IDs and parameter definitions. The end of the list must be indicated by a function ID of zero.
name Name of this client
Returns:
RPC_SUCCESS

Definition at line 8083 of file midas.c.

08084 {
08085    rpc_set_name(name);
08086    rpc_register_functions(rpc_get_internal_list(0), NULL);
08087    rpc_register_functions(list, NULL);
08088 
08089    return RPC_SUCCESS;
08090 }

INT rpc_register_functions ( const RPC_LIST *  new_list,
INT(*)(INT, void **)  func 
)

Register a set of RPC functions (both as clients or servers)

Parameters:
new_list Array of RPC_LIST structures containing function IDs and parameter definitions. The end of the list must be indicated by a function ID of zero.
func Default dispatch function
Returns:
RPC_SUCCESS, RPC_NO_MEMORY, RPC_DOUBLE_DEFINED

Definition at line 8103 of file midas.c.

Referenced by cm_connect_experiment1(), do_jrpc_rev0(), main(), and rpc_register_client().

08104 {
08105    INT i, j, iold, inew;
08106 
08107    /* count number of new functions */
08108    for (i = 0; new_list[i].id != 0; i++) {
08109       /* check double defined functions */
08110       for (j = 0; rpc_list != NULL && rpc_list[j].id != 0; j++)
08111          if (rpc_list[j].id == new_list[i].id)
08112             return RPC_DOUBLE_DEFINED;
08113    }
08114    inew = i;
08115 
08116    /* count number of existing functions */
08117    for (i = 0; rpc_list != NULL && rpc_list[i].id != 0; i++);
08118    iold = i;
08119 
08120    /* allocate new memory for rpc_list */
08121    if (rpc_list == NULL)
08122       rpc_list = (RPC_LIST *) M_MALLOC(sizeof(RPC_LIST) * (inew + 1));
08123    else
08124       rpc_list = (RPC_LIST *) realloc(rpc_list, sizeof(RPC_LIST) * (iold + inew + 1));
08125 
08126    if (rpc_list == NULL) {
08127       cm_msg(MERROR, "rpc_register_functions", "out of memory");
08128       return RPC_NO_MEMORY;
08129    }
08130 
08131    /* append new functions */
08132    for (i = iold; i < iold + inew; i++) {
08133       memcpy(rpc_list + i, new_list + i - iold, sizeof(RPC_LIST));
08134 
08135       /* set default dispatcher */
08136       if (rpc_list[i].dispatch == NULL)
08137          rpc_list[i].dispatch = func;
08138 
08139       /* check valid ID for user functions */
08140       if (new_list != rpc_get_internal_list(0) &&
08141           new_list != rpc_get_internal_list(1) && (rpc_list[i].id < RPC_MIN_ID
08142                                                    || rpc_list[i].id > RPC_MAX_ID))
08143          cm_msg(MERROR, "rpc_register_functions", "registered RPC function with invalid ID");
08144    }
08145 
08146    /* mark end of list */
08147    rpc_list[i].id = 0;
08148 
08149    return RPC_SUCCESS;
08150 }

INT rpc_send_event ( INT  buffer_handle,
void *  source,
INT  buf_size,
INT  async_flag,
INT  mode 
)

Fast send_event routine which bypasses the RPC layer and sends the event directly at the TCP level.

Parameters:
buffer_handle Handle of the buffer to send the event to. Must be obtained via bm_open_buffer.
source Address of the event to send. It must have a proper event header.
buf_size Size of event in bytes with header.
async_flag SYNC / ASYNC flag. In ASYNC mode, the function returns immediately if it cannot send the event over the network. In SYNC mode, it waits until the packet is sent (blocking).
mode Determines in which mode the event is sent. If zero, use RPC socket, if one, use special event socket to bypass RPC layer on the server side.
Returns:
BM_INVALID_PARAM, BM_ASYNC_RETURN, RPC_SUCCESS, RPC_NET_ERROR, RPC_NO_CONNECTION, RPC_EXCEED_BUFFER

Definition at line 10062 of file midas.c.

Referenced by receive_trigger_event(), and send_event().

10063 {
10064    INT i;
10065    NET_COMMAND *nc;
10066    unsigned long flag;
10067    BOOL would_block = 0;
10068    DWORD aligned_buf_size;
10069 
10070    aligned_buf_size = ALIGN8(buf_size);
10071    _rpc_sock = mode == 0 ? _server_connection.send_sock : _server_connection.event_sock;
10072 
10073    if ((INT) aligned_buf_size != (INT) (ALIGN8(((EVENT_HEADER *) source)->data_size + sizeof(EVENT_HEADER)))) {
10074       cm_msg(MERROR, "rpc_send_event", "event size mismatch");
10075       return BM_INVALID_PARAM;
10076    }
10077 
10078    if (!rpc_is_remote())
10079       return bm_send_event(buffer_handle, source, buf_size, async_flag);
10080 
10081    /* init network buffer */
10082    if (!_tcp_buffer)
10083       _tcp_buffer = (char *) M_MALLOC(NET_TCP_SIZE);
10084    if (!_tcp_buffer) {
10085       cm_msg(MERROR, "rpc_send_event", "not enough memory to allocate network buffer");
10086       return RPC_EXCEED_BUFFER;
10087    }
10088 
10089    /* check if not enough space in TCP buffer */
10090    if (aligned_buf_size + 4 * 8 + sizeof(NET_COMMAND_HEADER) >= (DWORD) (_opt_tcp_size - _tcp_wp)
10091        && _tcp_wp != _tcp_rp) {
10092       /* set socket to nonblocking IO */
10093       if (async_flag == ASYNC) {
10094          flag = 1;
10095 #ifdef OS_VXWORKS
10096          ioctlsocket(_rpc_sock, FIONBIO, (int) &flag);
10097 #else
10098          ioctlsocket(_rpc_sock, FIONBIO, &flag);
10099 #endif
10100       }
10101 
10102       i = send_tcp(_rpc_sock, _tcp_buffer + _tcp_rp, _tcp_wp - _tcp_rp, 0);
10103 
10104       if (i < 0)
10105 #ifdef OS_WINNT
10106          would_block = (WSAGetLastError() == WSAEWOULDBLOCK);
10107 #else
10108          would_block = (errno == EWOULDBLOCK);
10109 #endif
10110 
10111       /* set socket back to blocking IO */
10112       if (async_flag == ASYNC) {
10113          flag = 0;
10114 #ifdef OS_VXWORKS
10115          ioctlsocket(_rpc_sock, FIONBIO, (int) &flag);
10116 #else
10117          ioctlsocket(_rpc_sock, FIONBIO, &flag);
10118 #endif
10119       }
10120 
10121       /* increment read pointer */
10122       if (i > 0)
10123          _tcp_rp += i;
10124 
10125       /* check if whole buffer is sent */
10126       if (_tcp_rp == _tcp_wp)
10127          _tcp_rp = _tcp_wp = 0;
10128 
10129       if (i < 0 && !would_block) {
10130          cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10131          return RPC_NET_ERROR;
10132       }
10133 
10134       /* return if buffer is not emptied */
10135       if (_tcp_wp > 0)
10136          return BM_ASYNC_RETURN;
10137    }
10138 
10139    if (mode == 0) {
10140       nc = (NET_COMMAND *) (_tcp_buffer + _tcp_wp);
10141       nc->header.routine_id = RPC_BM_SEND_EVENT | TCP_FAST;
10142       nc->header.param_size = 4 * 8 + aligned_buf_size;
10143 
10144       /* assemble parameters manually */
10145       *((INT *) (&nc->param[0])) = buffer_handle;
10146       *((INT *) (&nc->param[8])) = buf_size;
10147 
10148       /* send events larger than optimal buffer size directly */
10149       if (aligned_buf_size + 4 * 8 + sizeof(NET_COMMAND_HEADER) >= (DWORD) _opt_tcp_size) {
10150          /* send header */
10151          i = send_tcp(_rpc_sock, _tcp_buffer + _tcp_wp, sizeof(NET_COMMAND_HEADER) + 16, 0);
10152          if (i <= 0) {
10153             cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10154             return RPC_NET_ERROR;
10155          }
10156 
10157          /* send data */
10158          i = send_tcp(_rpc_sock, (char *) source, aligned_buf_size, 0);
10159          if (i <= 0) {
10160             cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10161             return RPC_NET_ERROR;
10162          }
10163 
10164          /* send last two parameters */
10165          *((INT *) (&nc->param[0])) = buf_size;
10166          *((INT *) (&nc->param[8])) = 0;
10167          i = send_tcp(_rpc_sock, &nc->param[0], 16, 0);
10168          if (i <= 0) {
10169             cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10170             return RPC_NET_ERROR;
10171          }
10172       } else {
10173          /* copy event */
10174          memcpy(&nc->param[16], source, buf_size);
10175 
10176          /* last two parameters (buf_size and async_flag */
10177          *((INT *) (&nc->param[16 + aligned_buf_size])) = buf_size;
10178          *((INT *) (&nc->param[24 + aligned_buf_size])) = 0;
10179 
10180          _tcp_wp += nc->header.param_size + sizeof(NET_COMMAND_HEADER);
10181       }
10182 
10183    } else {
10184 
10185       /* send events larger than optimal buffer size directly */
10186       if (aligned_buf_size + 4 * 8 + sizeof(INT) >= (DWORD) _opt_tcp_size) {
10187          /* send buffer */
10188          i = send_tcp(_rpc_sock, (char *) &buffer_handle, sizeof(INT), 0);
10189          if (i <= 0) {
10190             cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10191             return RPC_NET_ERROR;
10192          }
10193 
10194          /* send data */
10195          i = send_tcp(_rpc_sock, (char *) source, aligned_buf_size, 0);
10196          if (i <= 0) {
10197             cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10198             return RPC_NET_ERROR;
10199          }
10200       } else {
10201          /* copy event */
10202          *((INT *) (_tcp_buffer + _tcp_wp)) = buffer_handle;
10203          _tcp_wp += sizeof(INT);
10204          memcpy(_tcp_buffer + _tcp_wp, source, buf_size);
10205 
10206          _tcp_wp += aligned_buf_size;
10207       }
10208    }
10209 
10210    return RPC_SUCCESS;
10211 }

INT rpc_set_option ( HNDLE  hConn,
INT  item,
INT  value 
)

Set RPC option

Parameters:
hConn RPC connection handle, -1 for server connection, -2 for rpc connect timeout
item One of RPC_Oxxx
value Value to set
Returns:
RPC_SUCCESS

Definition at line 9135 of file midas.c.

Referenced by bm_receive_event(), cm_transition1(), command_loop(), db_send_changed_records(), main(), and update_odb().

09136 {
09137    switch (item) {
09138    case RPC_OTIMEOUT:
09139       if (hConn == -1)
09140          _server_connection.rpc_timeout = value;
09141       else if (hConn == -2)
09142          _rpc_connect_timeout = value;
09143       else
09144          _client_connection[hConn - 1].rpc_timeout = value;
09145       break;
09146 
09147    case RPC_OTRANSPORT:
09148       if (hConn == -1)
09149          _server_connection.transport = value;
09150       else
09151          _client_connection[hConn - 1].transport = value;
09152       break;
09153 
09154    case RPC_NODELAY:
09155       if (hConn == -1)
09156          setsockopt(_server_connection.send_sock, IPPROTO_TCP, TCP_NODELAY, (char *) &value, sizeof(value));
09157       else
09158          setsockopt(_client_connection[hConn - 1].send_sock, IPPROTO_TCP, TCP_NODELAY, (char *) &value,
09159                     sizeof(value));
09160       break;
09161 
09162    default:
09163       cm_msg(MERROR, "rpc_set_option", "invalid argument");
09164       break;
09165    }
09166 
09167    return 0;
09168 }


Midas DOC Version 3.0.0 ---- PSI Stefan Ritt ----
Contributions: Pierre-Andre Amaudruz - Sergio Ballestrero - Suzannah Daviel - Doxygen - Peter Green - Qing Gu - Greg Hackman - Gertjan Hofman - Paul Knowles - Exaos Lee - Rudi Meier - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Renee Poutissou - Tamsen Schurman - Andreas Suter - Jan M.Wouters - Piotr Adam Zolnierczuk