MIDAS
Loading...
Searching...
No Matches
Event Buffer Functions (bm_xxx)

Classes

struct  BUFFER_INFO
 
struct  EVENT_DEFRAG_BUFFER
 

Macros

#define MAX_DEFRAG_EVENTS   10
 

Functions

static int bm_validate_client_index_locked (bm_lock_buffer_guard &pbuf_guard)
 
INT bm_match_event (short int event_id, short int trigger_mask, const EVENT_HEADER *pevent)
 
void bm_remove_client_locked (BUFFER_HEADER *pheader, int j)
 
static void bm_cleanup_buffer_locked (BUFFER *pbuf, const char *who, DWORD actual_time)
 
static void bm_update_last_activity (DWORD millitime)
 
static BOOL bm_validate_rp (const char *who, const BUFFER_HEADER *pheader, int rp)
 
static int bm_incr_rp_no_check (const BUFFER_HEADER *pheader, int rp, int total_size)
 
static int bm_next_rp (const char *who, const BUFFER_HEADER *pheader, const char *pdata, int rp)
 
static int bm_validate_buffer_locked (const BUFFER *pbuf)
 
static void bm_reset_buffer_locked (BUFFER *pbuf)
 
static void bm_clear_buffer_statistics (HNDLE hDB, BUFFER *pbuf)
 
static void bm_write_buffer_statistics_to_odb_copy (HNDLE hDB, const char *buffer_name, const char *client_name, int client_index, BUFFER_INFO *pbuf, BUFFER_HEADER *pheader)
 
static void bm_write_buffer_statistics_to_odb (HNDLE hDB, BUFFER *pbuf, BOOL force)
 
INT bm_open_buffer (const char *buffer_name, INT buffer_size, INT *buffer_handle)
 
INT bm_get_buffer_handle (const char *buffer_name, INT *buffer_handle)
 
INT bm_close_buffer (INT buffer_handle)
 
INT bm_close_all_buffers (void)
 
INT bm_write_statistics_to_odb (void)
 
INT bm_set_cache_size (INT buffer_handle, size_t read_size, size_t write_size)
 
INT bm_compose_event (EVENT_HEADER *event_header, short int event_id, short int trigger_mask, DWORD data_size, DWORD serial)
 
INT bm_compose_event_threadsafe (EVENT_HEADER *event_header, short int event_id, short int trigger_mask, DWORD data_size, DWORD *serial)
 
INT bm_add_event_request (INT buffer_handle, short int event_id, short int trigger_mask, INT sampling_type, EVENT_HANDLER *func, INT request_id)
 
INT bm_request_event (HNDLE buffer_handle, short int event_id, short int trigger_mask, INT sampling_type, HNDLE *request_id, EVENT_HANDLER *func)
 
INT bm_remove_event_request (INT buffer_handle, INT request_id)
 
INT bm_delete_request (INT request_id)
 
static void bm_validate_client_pointers_locked (const BUFFER_HEADER *pheader, BUFFER_CLIENT *pclient)
 
static BOOL bm_update_read_pointer_locked (const char *caller_name, BUFFER_HEADER *pheader)
 
static void bm_wakeup_producers_locked (const BUFFER_HEADER *pheader, const BUFFER_CLIENT *pc)
 
static void bm_dispatch_event (int buffer_handle, EVENT_HEADER *pevent)
 
static void bm_incr_read_cache_locked (BUFFER *pbuf, int total_size)
 
static BOOL bm_peek_read_cache_locked (BUFFER *pbuf, EVENT_HEADER **ppevent, int *pevent_size, int *ptotal_size)
 
static int bm_peek_buffer_locked (BUFFER *pbuf, BUFFER_HEADER *pheader, BUFFER_CLIENT *pc, EVENT_HEADER **ppevent, int *pevent_size, int *ptotal_size)
 
static void bm_read_from_buffer_locked (const BUFFER_HEADER *pheader, int rp, char *buf, int event_size)
 
static void bm_read_from_buffer_locked (const BUFFER_HEADER *pheader, int rp, std::vector< char > *vecptr, int event_size)
 
static BOOL bm_check_requests (const BUFFER_CLIENT *pc, const EVENT_HEADER *pevent)
 
static int bm_wait_for_more_events_locked (bm_lock_buffer_guard &pbuf_guard, BUFFER_CLIENT *pc, int timeout_msec, BOOL unlock_read_cache)
 
static int bm_fill_read_cache_locked (bm_lock_buffer_guard &pbuf_guard, int timeout_msec)
 
static void bm_convert_event_header (EVENT_HEADER *pevent, int convert_flags)
 
static int bm_wait_for_free_space_locked (bm_lock_buffer_guard &pbuf_guard, int timeout_msec, int requested_space, bool unlock_write_cache)
 
static void bm_write_to_buffer_locked (BUFFER_HEADER *pheader, int sg_n, const char *const sg_ptr[], const size_t sg_len[], size_t total_size)
 
static int bm_find_first_request_locked (BUFFER_CLIENT *pc, const EVENT_HEADER *pevent)
 
static void bm_notify_reader_locked (BUFFER_HEADER *pheader, BUFFER_CLIENT *pc, int old_write_pointer, int request_id)
 
INT bm_send_event (INT buffer_handle, const EVENT_HEADER *pevent, int unused, int timeout_msec)
 
int bm_send_event_vec (int buffer_handle, const std::vector< char > &event, int timeout_msec)
 
int bm_send_event_vec (int buffer_handle, const std::vector< std::vector< char > > &event, int timeout_msec)
 
static INT bm_flush_cache_locked (bm_lock_buffer_guard &pbuf_guard, int timeout_msec)
 
int bm_send_event_sg (int buffer_handle, int sg_n, const char *const sg_ptr[], const size_t sg_len[], int timeout_msec)
 
static int bm_flush_cache_rpc (int buffer_handle, int timeout_msec)
 
INT bm_flush_cache (int buffer_handle, int timeout_msec)
 
static INT bm_read_buffer (BUFFER *pbuf, INT buffer_handle, void **bufptr, void *buf, INT *buf_size, std::vector< char > *vecptr, int timeout_msec, int convert_flags, BOOL dispatch)
 
static INT bm_receive_event_rpc (INT buffer_handle, void *buf, int *buf_size, EVENT_HEADER **ppevent, std::vector< char > *pvec, int timeout_msec)
 
static INT bm_receive_event_rpc_cxx (INT buffer_handle, void *buf, int *buf_size, EVENT_HEADER **ppevent, std::vector< char > *pvec, int timeout_msec)
 
INT bm_receive_event (INT buffer_handle, void *destination, INT *buf_size, int timeout_msec)
 
INT bm_receive_event_alloc (INT buffer_handle, EVENT_HEADER **ppevent, int timeout_msec)
 
INT bm_receive_event_vec (INT buffer_handle, std::vector< char > *pvec, int timeout_msec)
 
static int bm_skip_event (BUFFER *pbuf)
 
INT bm_skip_event (INT buffer_handle)
 
static INT bm_push_buffer (BUFFER *pbuf, int buffer_handle)
 
INT bm_check_buffers ()
 
INT bm_poll_event ()
 
INT bm_empty_buffers ()
 

Variables

static DWORD _bm_max_event_size = 0
 
static int _bm_lock_timeout = 5 * 60 * 1000
 
static double _bm_mutex_timeout_sec = _bm_lock_timeout/1000 + 15.000
 
static EVENT_DEFRAG_BUFFER defrag_buffer [MAX_DEFRAG_EVENTS]
 

Detailed Description

dox dox


Macro Definition Documentation

◆ MAX_DEFRAG_EVENTS

#define MAX_DEFRAG_EVENTS   10

dox

Definition at line 11420 of file midas.cxx.

Function Documentation

◆ bm_add_event_request()

INT bm_add_event_request ( INT  buffer_handle,
short int  event_id,
short int  trigger_mask,
INT  sampling_type,
EVENT_HANDLER func,
INT  request_id 
)

dox

Definition at line 8334 of file midas.cxx.

8378{
8379 if (rpc_is_remote())
8380 return rpc_call(RPC_BM_ADD_EVENT_REQUEST, buffer_handle, event_id,
8381 trigger_mask, sampling_type, (INT) (POINTER_T) func, request_id);
8382
8383#ifdef LOCAL_ROUTINES
8384 {
8385 int status = 0;
8386
8387 BUFFER *pbuf = bm_get_buffer("bm_add_event_request", buffer_handle, &status);
8388
8389 if (!pbuf)
8390 return status;
8391
8392 /* lock buffer */
8393 bm_lock_buffer_guard pbuf_guard(pbuf);
8394
8395 if (!pbuf_guard.is_locked())
8396 return pbuf_guard.get_status();
8397
8398 /* avoid callback/non callback requests */
8399 if (func == NULL && pbuf->callback) {
8400 pbuf_guard.unlock(); // unlock before cm_msg()
8401 cm_msg(MERROR, "bm_add_event_request", "mixing callback/non callback requests not possible");
8402 return BM_INVALID_MIXING;
8403 }
8404
8405 /* do not allow GET_RECENT with nonzero cache size */
8406 if (sampling_type == GET_RECENT && pbuf->read_cache_size > 0) {
8407 pbuf_guard.unlock(); // unlock before cm_msg()
8408 cm_msg(MERROR, "bm_add_event_request", "GET_RECENT request not possible if read cache is enabled");
8409 return BM_INVALID_PARAM;
8410 }
8411
8412 /* get a pointer to the proper client structure */
8413 BUFFER_CLIENT *pclient = bm_get_my_client_locked(pbuf_guard);
8414
8415 /* look for a empty request entry */
8416 int i;
8417 for (i = 0; i < MAX_EVENT_REQUESTS; i++)
8418 if (!pclient->event_request[i].valid)
8419 break;
8420
8421 if (i == MAX_EVENT_REQUESTS) {
8422 // implicit unlock
8423 return BM_NO_MEMORY;
8424 }
8425
8426 /* setup event_request structure */
8427 pclient->event_request[i].id = request_id;
8428 pclient->event_request[i].valid = TRUE;
8429 pclient->event_request[i].event_id = event_id;
8431 pclient->event_request[i].sampling_type = sampling_type;
8432
8433 pclient->all_flag = pclient->all_flag || (sampling_type & GET_ALL);
8434
8435 pbuf->get_all_flag = pclient->all_flag;
8436
8437 /* set callback flag in buffer structure */
8438 if (func != NULL)
8439 pbuf->callback = TRUE;
8440
8441 /*
8442 Save the index of the last request in the list so that later only the
8443 requests 0..max_request_index-1 have to be searched through.
8444 */
8445
8446 if (i + 1 > pclient->max_request_index)
8447 pclient->max_request_index = i + 1;
8448 }
8449#endif /* LOCAL_ROUTINES */
8450
8451 return BM_SUCCESS;
8452}
static BUFFER_CLIENT * bm_get_my_client_locked(bm_lock_buffer_guard &pbuf_guard)
Definition midas.cxx:6017
static BUFFER * bm_get_buffer(const char *who, INT buffer_handle, int *pstatus)
Definition midas.cxx:6633
#define BM_INVALID_PARAM
Definition midas.h:619
#define BM_NO_MEMORY
Definition midas.h:607
#define BM_INVALID_MIXING
Definition midas.h:621
#define BM_SUCCESS
Definition midas.h:605
#define GET_ALL
Definition midas.h:321
#define GET_RECENT
Definition midas.h:323
#define MERROR
Definition midas.h:559
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:931
#define RPC_BM_ADD_EVENT_REQUEST
Definition mrpc.h:43
bool rpc_is_remote(void)
Definition midas.cxx:12901
INT rpc_call(DWORD routine_id,...)
Definition midas.cxx:14124
INT i
Definition mdump.cxx:32
int INT
Definition midas.h:129
#define TRUE
Definition midas.h:182
#define MAX_EVENT_REQUESTS
Definition midas.h:275
#define POINTER_T
Definition midas.h:166
#define trigger_mask
#define event_id
DWORD status
Definition odbhist.cxx:39
BOOL all_flag
Definition midas.h:950
EVENT_REQUEST event_request[MAX_EVENT_REQUESTS]
Definition midas.h:954
INT max_request_index
Definition midas.h:942
BOOL get_all_flag
Definition midas.h:1009
BOOL callback
Definition midas.h:1007
std::atomic< size_t > read_cache_size
Definition midas.h:995
short int event_id
Definition midas.h:930
short int trigger_mask
Definition midas.h:931
INT sampling_type
Definition midas.h:932
BOOL valid
Definition midas.h:929
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_check_buffers()

INT bm_check_buffers ( void  )

Check if any requested event is waiting in a buffer

Returns
TRUE More events are waiting
FALSE No more events are waiting

Definition at line 11102 of file midas.cxx.

11102 {
11103#ifdef LOCAL_ROUTINES
11104 {
11105 INT status = 0;
11106 BOOL bMore;
11107 DWORD start_time;
11108 //static DWORD last_time = 0;
11109
11110 /* if running as a server, buffer checking is done by client
11111 via ASYNC bm_receive_event */
11112 if (rpc_is_mserver()) {
11113 return FALSE;
11114 }
11115
11116 bMore = FALSE;
11117 start_time = ss_millitime();
11118
11119 std::vector<BUFFER*> mybuffers;
11120
11121 gBuffersMutex.lock();
11122 mybuffers = gBuffers;
11123 gBuffersMutex.unlock();
11124
11125 /* go through all buffers */
11126 for (size_t idx = 0; idx < mybuffers.size(); idx++) {
11127 BUFFER* pbuf = mybuffers[idx];
11128
11129 if (!pbuf || !pbuf->attached)
11130 continue;
11131
11132 //int count_loops = 0;
11133 while (1) {
11134 if (pbuf->attached) {
11135 /* one bm_push_event could cause a run stop and a buffer close, which
11136 * would crash the next call to bm_push_event(). So check for valid
11137 * buffer on each call */
11138
11139 /* this is what happens:
11140 * bm_push_buffer() may call a user callback function
11141 * user callback function may indirectly call bm_close() of this buffer,
11142 * i.e. if it stops the run,
11143 * bm_close() will set pbuf->attached to false, but will not delete pbuf or touch gBuffers
11144 * here we will see pbuf->attched is false and quit this loop
11145 */
11146
11147 status = bm_push_buffer(pbuf, idx + 1);
11148
11149 if (status == BM_CORRUPTED) {
11150 return status;
11151 }
11152
11153 //printf("bm_check_buffers: bm_push_buffer() returned %d, loop %d, time %d\n", status, count_loops, ss_millitime() - start_time);
11154
11155 if (status != BM_MORE_EVENTS) {
11156 //DWORD t = ss_millitime() - start_time;
11157 //printf("bm_check_buffers: index %d, period %d, elapsed %d, loop %d, no more events\n", idx, start_time - last_time, t, count_loops);
11158 break;
11159 }
11160
11161 // count_loops++;
11162 }
11163
11164 // NB: this code has a logic error: if 2 buffers always have data,
11165 // this timeout will cause us to exit reading the 1st buffer
11166 // after 1000 msec, then we read the 2nd buffer exactly once,
11167 // and exit the loop because the timeout is still active -
11168 // we did not reset "start_time" when we started reading
11169 // from the 2nd buffer. Result is that we always read all
11170 // the data in a loop from the 1st buffer, but read just
11171 // one event from the 2nd buffer, resulting in severe unfairness.
11172
11173 /* stop after one second */
11174 DWORD t = ss_millitime() - start_time;
11175 if (t > 1000) {
11176 //printf("bm_check_buffers: index %d, period %d, elapsed %d, loop %d, timeout.\n", idx, start_time - last_time, t, count_loops);
11177 bMore = TRUE;
11178 break;
11179 }
11180 }
11181 }
11182
11183 //last_time = start_time;
11184
11185 return bMore;
11186
11187 }
11188#else /* LOCAL_ROUTINES */
11189
11190 return FALSE;
11191
11192#endif
11193}
#define FALSE
Definition cfortran.h:309
static INT bm_push_buffer(BUFFER *pbuf, int buffer_handle)
Definition midas.cxx:11050
#define BM_MORE_EVENTS
Definition midas.h:620
#define BM_CORRUPTED
Definition midas.h:623
unsigned int DWORD
Definition mcstd.h:51
DWORD ss_millitime()
Definition system.cxx:3472
bool rpc_is_mserver(void)
Definition midas.cxx:12958
static std::mutex gBuffersMutex
Definition midas.cxx:195
static std::vector< BUFFER * > gBuffers
Definition midas.cxx:196
DWORD BOOL
Definition midas.h:105
std::atomic_bool attached
Definition midas.h:988
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_check_requests()

static BOOL bm_check_requests ( const BUFFER_CLIENT pc,
const EVENT_HEADER pevent 
)
static

Definition at line 8986 of file midas.cxx.

8986 {
8987
8988 BOOL is_requested = FALSE;
8989 int i;
8990 for (i = 0; i < pc->max_request_index; i++) {
8991 const EVENT_REQUEST *prequest = pc->event_request + i;
8992 if (prequest->valid) {
8993 if (bm_match_event(prequest->event_id, prequest->trigger_mask, pevent)) {
8994 /* check if this is a recent event */
8995 if (prequest->sampling_type == GET_RECENT) {
8996 if (ss_time() - pevent->time_stamp > 1) {
8997 /* skip that event */
8998 continue;
8999 }
9000 }
9001
9002 is_requested = TRUE;
9003 break;
9004 }
9005 }
9006 }
9007 return is_requested;
9008}
INT bm_match_event(short int event_id, short int trigger_mask, const EVENT_HEADER *pevent)
Definition midas.cxx:6033
DWORD ss_time()
Definition system.cxx:3541
DWORD time_stamp
Definition midas.h:856
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_cleanup_buffer_locked()

static void bm_cleanup_buffer_locked ( BUFFER pbuf,
const char *  who,
DWORD  actual_time 
)
static

Check all clients on buffer, remove invalid clients

Definition at line 6084 of file midas.cxx.

6084 {
6085 BUFFER_HEADER *pheader;
6086 BUFFER_CLIENT *pbclient;
6087 int j;
6088
6089 pheader = pbuf->buffer_header;
6090 pbclient = pheader->client;
6091
6092 /* now check other clients */
6093 for (j = 0; j < pheader->max_client_index; j++, pbclient++) {
6094 if (pbclient->pid) {
6095 if (!ss_pid_exists(pbclient->pid)) {
6096 cm_msg(MINFO, "bm_cleanup",
6097 "Client \'%s\' on buffer \'%s\' removed by %s because process pid %d does not exist", pbclient->name,
6098 pheader->name, who, pbclient->pid);
6099
6100 bm_remove_client_locked(pheader, j);
6101 continue;
6102 }
6103 }
6104
6105 /* If client process has no activity, clear its buffer entry. */
6106 if (pbclient->pid && pbclient->watchdog_timeout > 0) {
6107 DWORD tdiff = actual_time - pbclient->last_activity;
6108#if 0
6109 printf("buffer [%s] client [%-32s] times 0x%08x 0x%08x, diff 0x%08x %5d, timeout %d\n",
6110 pheader->name,
6111 pbclient->name,
6112 pbclient->last_activity,
6114 tdiff,
6115 tdiff,
6116 pbclient->watchdog_timeout);
6117#endif
6118 if (actual_time > pbclient->last_activity &&
6119 tdiff > pbclient->watchdog_timeout) {
6120
6121 cm_msg(MINFO, "bm_cleanup", "Client \'%s\' on buffer \'%s\' removed by %s (idle %1.1lfs, timeout %1.0lfs)",
6122 pbclient->name, pheader->name, who,
6123 tdiff / 1000.0,
6124 pbclient->watchdog_timeout / 1000.0);
6125
6126 bm_remove_client_locked(pheader, j);
6127 }
6128 }
6129 }
6130}
void bm_remove_client_locked(BUFFER_HEADER *pheader, int j)
Definition midas.cxx:6053
#define MINFO
Definition midas.h:560
BOOL ss_pid_exists(int pid)
Definition system.cxx:1442
DWORD actual_time
Definition mfe.cxx:37
INT j
Definition odbhist.cxx:40
DWORD watchdog_timeout
Definition midas.h:952
DWORD last_activity
Definition midas.h:951
char name[NAME_LENGTH]
Definition midas.h:936
char name[NAME_LENGTH]
Definition midas.h:959
INT max_client_index
Definition midas.h:961
BUFFER_CLIENT client[MAX_CLIENTS]
Definition midas.h:968
BUFFER_HEADER * buffer_header
Definition midas.h:993
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_clear_buffer_statistics()

static void bm_clear_buffer_statistics ( HNDLE  hDB,
BUFFER pbuf 
)
static

Definition at line 6426 of file midas.cxx.

6426 {
6427 std::string str = msprintf("/System/buffers/%s/Clients/%s/writes_blocked_by", pbuf->buffer_name, pbuf->client_name);
6428 //printf("delete [%s]\n", str);
6429 db_delete(hDB, 0, str.c_str());
6430}
INT db_delete(HNDLE hDB, HNDLE hKeyRoot, const char *odb_path)
Definition odb.cxx:4494
HNDLE hDB
main ODB handle
Definition mana.cxx:207
std::string msprintf(const char *format,...)
Definition midas.cxx:419
char str[256]
Definition odbhist.cxx:33
char client_name[NAME_LENGTH]
Definition midas.h:991
char buffer_name[NAME_LENGTH]
Definition midas.h:992
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_close_all_buffers()

INT bm_close_all_buffers ( void  )

Close all open buffers

Returns
BM_SUCCESS

Definition at line 7263 of file midas.cxx.

7263 {
7264 if (rpc_is_remote())
7266
7267#ifdef LOCAL_ROUTINES
7268 {
7270
7271 gBuffersMutex.lock();
7272 size_t nbuf = gBuffers.size();
7273 gBuffersMutex.unlock();
7274
7275 for (size_t i = nbuf; i > 0; i--) {
7277 }
7278
7279 gBuffersMutex.lock();
7280 for (size_t i=0; i< gBuffers.size(); i++) {
7281 BUFFER* pbuf = gBuffers[i];
7282 if (!pbuf)
7283 continue;
7284 delete pbuf;
7285 pbuf = NULL;
7286 gBuffers[i] = NULL;
7287 }
7288 gBuffersMutex.unlock();
7289 }
7290#endif /* LOCAL_ROUTINES */
7291
7292 return BM_SUCCESS;
7293}
INT bm_close_buffer(INT buffer_handle)
Definition midas.cxx:7116
int cm_msg_close_buffer(void)
Definition midas.cxx:501
#define RPC_BM_CLOSE_ALL_BUFFERS
Definition mrpc.h:38
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_close_buffer()

INT bm_close_buffer ( INT  buffer_handle)

Closes an event buffer previously opened with bm_open_buffer().

Parameters
buffer_handlebuffer handle
Returns
BM_SUCCESS, BM_INVALID_HANDLE

Definition at line 7116 of file midas.cxx.

7116 {
7117 //printf("bm_close_buffer: handle %d\n", buffer_handle);
7118
7119 if (rpc_is_remote())
7120 return rpc_call(RPC_BM_CLOSE_BUFFER, buffer_handle);
7121
7122#ifdef LOCAL_ROUTINES
7123 {
7124 int status = 0;
7125
7126 BUFFER *pbuf = bm_get_buffer(NULL, buffer_handle, &status);
7127
7128 if (!pbuf)
7129 return status;
7130
7131 //printf("bm_close_buffer: handle %d, name [%s]\n", buffer_handle, pheader->name);
7132
7133 int i;
7134
7135 { /* delete all requests for this buffer */
7136 _request_list_mutex.lock();
7137 std::vector<EventRequest> request_list_copy = _request_list;
7138 _request_list_mutex.unlock();
7139 for (size_t i = 0; i < request_list_copy.size(); i++) {
7140 if (request_list_copy[i].buffer_handle == buffer_handle) {
7142 }
7143 }
7144 }
7145
7146 HNDLE hDB;
7148
7149 if (hDB) {
7150 /* write statistics to odb */
7152 }
7153
7154 /* lock buffer in correct order */
7155
7157
7158 if (status != BM_SUCCESS) {
7159 return status;
7160 }
7161
7163
7164 if (status != BM_SUCCESS) {
7165 pbuf->read_cache_mutex.unlock();
7166 return status;
7167 }
7168
7169 bm_lock_buffer_guard pbuf_guard(pbuf);
7170
7171 if (!pbuf_guard.is_locked()) {
7172 pbuf->write_cache_mutex.unlock();
7173 pbuf->read_cache_mutex.unlock();
7174 return pbuf_guard.get_status();
7175 }
7176
7177 BUFFER_HEADER *pheader = pbuf->buffer_header;
7178
7179 /* mark entry in _buffer as empty */
7180 pbuf->attached = false;
7181
7182 BUFFER_CLIENT* pclient = bm_get_my_client_locked(pbuf_guard);
7183
7184 if (pclient) {
7185 /* clear entry from client structure in buffer header */
7186 memset(pclient, 0, sizeof(BUFFER_CLIENT));
7187 }
7188
7189 /* calculate new max_client_index entry */
7190 for (i = MAX_CLIENTS - 1; i >= 0; i--)
7191 if (pheader->client[i].pid != 0)
7192 break;
7193 pheader->max_client_index = i + 1;
7194
7195 /* count new number of clients */
7196 int j = 0;
7197 for (i = MAX_CLIENTS - 1; i >= 0; i--)
7198 if (pheader->client[i].pid != 0)
7199 j++;
7200 pheader->num_clients = j;
7201
7202 int destroy_flag = (pheader->num_clients == 0);
7203
7204 // we hold the locks on the read cache and the write cache.
7205
7206 /* free cache */
7207 if (pbuf->read_cache_size > 0) {
7208 free(pbuf->read_cache);
7209 pbuf->read_cache = NULL;
7210 pbuf->read_cache_size = 0;
7211 pbuf->read_cache_rp = 0;
7212 pbuf->read_cache_wp = 0;
7213 }
7214
7215 if (pbuf->write_cache_size > 0) {
7216 free(pbuf->write_cache);
7217 pbuf->write_cache = NULL;
7218 pbuf->write_cache_size = 0;
7219 pbuf->write_cache_rp = 0;
7220 pbuf->write_cache_wp = 0;
7221 }
7222
7223 /* check if anyone is waiting and wake him up */
7224
7225 for (int i = 0; i < pheader->max_client_index; i++) {
7226 BUFFER_CLIENT *pclient = pheader->client + i;
7227 if (pclient->pid && (pclient->write_wait || pclient->read_wait))
7228 ss_resume(pclient->port, "B ");
7229 }
7230
7231 /* unmap shared memory, delete it if we are the last */
7232
7233 ss_shm_close(pbuf->buffer_name, pbuf->buffer_header, pbuf->shm_size, pbuf->shm_handle, destroy_flag);
7234
7235 /* after ss_shm_close() these are invalid: */
7236
7237 pheader = NULL;
7238 pbuf->buffer_header = NULL;
7239 pbuf->shm_size = 0;
7240 pbuf->shm_handle = 0;
7241
7242 /* unlock buffer in correct order */
7243
7244 pbuf_guard.unlock();
7245
7246 pbuf->write_cache_mutex.unlock();
7247 pbuf->read_cache_mutex.unlock();
7248
7249 /* delete semaphore */
7250
7251 ss_semaphore_delete(pbuf->semaphore, destroy_flag);
7252 }
7253#endif /* LOCAL_ROUTINES */
7254
7255 return BM_SUCCESS;
7256}
INT bm_delete_request(INT request_id)
Definition midas.cxx:8604
static void bm_write_buffer_statistics_to_odb(HNDLE hDB, BUFFER *pbuf, BOOL force)
Definition midas.cxx:6597
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3027
static int bm_lock_buffer_read_cache(BUFFER *pbuf)
Definition midas.cxx:7924
static int bm_lock_buffer_write_cache(BUFFER *pbuf)
Definition midas.cxx:7945
INT ss_resume(INT port, const char *message)
Definition system.cxx:4923
INT ss_semaphore_delete(HNDLE semaphore_handle, INT destroy_flag)
Definition system.cxx:2948
INT ss_shm_close(const char *name, void *adr, size_t shm_size, HNDLE handle, INT destroy_flag)
Definition system.cxx:757
#define RPC_BM_CLOSE_BUFFER
Definition mrpc.h:37
static std::vector< EventRequest > _request_list
Definition midas.cxx:220
static std::mutex _request_list_mutex
Definition midas.cxx:219
#define MAX_CLIENTS
Definition midas.h:274
INT HNDLE
Definition midas.h:132
INT write_wait
Definition midas.h:948
BOOL read_wait
Definition midas.h:947
INT num_clients
Definition midas.h:960
HNDLE semaphore
Definition midas.h:1004
size_t read_cache_rp
Definition midas.h:997
std::timed_mutex read_cache_mutex
Definition midas.h:994
std::timed_mutex write_cache_mutex
Definition midas.h:999
size_t shm_size
Definition midas.h:1006
char * read_cache
Definition midas.h:996
size_t write_cache_rp
Definition midas.h:1002
size_t write_cache_wp
Definition midas.h:1003
char * write_cache
Definition midas.h:1001
size_t read_cache_wp
Definition midas.h:998
std::atomic< size_t > write_cache_size
Definition midas.h:1000
INT shm_handle
Definition midas.h:1005
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_compose_event()

INT bm_compose_event ( EVENT_HEADER event_header,
short int  event_id,
short int  trigger_mask,
DWORD  data_size,
DWORD  serial 
)

Compose a Midas event header. An event header can usually be set-up manually or through this routine. If the data size of the event is not known when the header is composed, it can be set later with event_header->data-size = <...> Following structure is created at the beginning of an event

typedef struct {
short int event_id;
short int trigger_mask;
DWORD data_size;
char event[1000];
bm_compose_event((EVENT_HEADER *)event, 1, 0, 100, 1);
*(event+sizeof(EVENT_HEADER)) = <...>
INT bm_compose_event(EVENT_HEADER *event_header, short int event_id, short int trigger_mask, DWORD data_size, DWORD serial)
Definition midas.cxx:8301
#define serial_number
#define time_stamp
Parameters
event_headerpointer to the event header
event_idevent ID of the event
trigger_masktrigger mask of the event
data_sizesize if the data part of the event in bytes
serialserial number
Returns
BM_SUCCESS

Definition at line 8301 of file midas.cxx.

8302{
8303 event_header->event_id = event_id;
8304 event_header->trigger_mask = trigger_mask;
8305 event_header->data_size = data_size;
8306 event_header->time_stamp = ss_time();
8307 event_header->serial_number = serial;
8308
8309 return BM_SUCCESS;
8310}
INT serial
Definition minife.c:20
short int event_id
Definition midas.h:853
DWORD data_size
Definition midas.h:857
DWORD serial_number
Definition midas.h:855
short int trigger_mask
Definition midas.h:854
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_compose_event_threadsafe()

INT bm_compose_event_threadsafe ( EVENT_HEADER event_header,
short int  event_id,
short int  trigger_mask,
DWORD  data_size,
DWORD serial 
)

Definition at line 8312 of file midas.cxx.

8313{
8314 static std::mutex mutex;
8315
8316 event_header->event_id = event_id;
8317 event_header->trigger_mask = trigger_mask;
8318 event_header->data_size = data_size;
8319 event_header->time_stamp = ss_time();
8320 {
8321 std::lock_guard<std::mutex> lock(mutex);
8322 event_header->serial_number = *serial;
8323 *serial = *serial + 1;
8324 // implicit unlock
8325 }
8326
8327 return BM_SUCCESS;
8328}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_convert_event_header()

static void bm_convert_event_header ( EVENT_HEADER pevent,
int  convert_flags 
)
static

Definition at line 9089 of file midas.cxx.

9089 {
9090 /* now convert event header */
9091 if (convert_flags) {
9092 rpc_convert_single(&pevent->event_id, TID_INT16, RPC_OUTGOING, convert_flags);
9093 rpc_convert_single(&pevent->trigger_mask, TID_INT16, RPC_OUTGOING, convert_flags);
9094 rpc_convert_single(&pevent->serial_number, TID_UINT32, RPC_OUTGOING, convert_flags);
9095 rpc_convert_single(&pevent->time_stamp, TID_UINT32, RPC_OUTGOING, convert_flags);
9096 rpc_convert_single(&pevent->data_size, TID_UINT32, RPC_OUTGOING, convert_flags);
9097 }
9098}
#define TID_UINT32
Definition midas.h:337
#define TID_INT16
Definition midas.h:335
void rpc_convert_single(void *data, INT tid, INT flags, INT convert_flags)
Definition midas.cxx:11821
#define RPC_OUTGOING
Definition midas.h:1568
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_delete_request()

INT bm_delete_request ( INT  request_id)

Deletes an event request previously done with bm_request_event(). When an event request gets deleted, events of that requested type are not received any more. When a buffer is closed via bm_close_buffer(), all event requests from that buffer are deleted automatically

Parameters
request_idrequest identifier given by bm_request_event()
Returns
BM_SUCCESS, BM_INVALID_HANDLE

Definition at line 8604 of file midas.cxx.

8605{
8606 _request_list_mutex.lock();
8607
8608 if (request_id < 0 || size_t(request_id) >= _request_list.size()) {
8609 _request_list_mutex.unlock();
8610 return BM_INVALID_HANDLE;
8611 }
8612
8613 int buffer_handle = _request_list[request_id].buffer_handle;
8614
8615 _request_list[request_id].clear();
8616
8617 _request_list_mutex.unlock();
8618
8619 /* remove request entry from buffer */
8620 return bm_remove_event_request(buffer_handle, request_id);
8621}
INT bm_remove_event_request(INT buffer_handle, INT request_id)
Definition midas.cxx:8538
#define BM_INVALID_HANDLE
Definition midas.h:609
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_dispatch_event()

static void bm_dispatch_event ( int  buffer_handle,
EVENT_HEADER pevent 
)
static

Definition at line 8843 of file midas.cxx.

8844{
8845 _request_list_mutex.lock();
8846 bool locked = true;
8847 size_t n = _request_list.size();
8848 /* call dispatcher */
8849 for (size_t i = 0; i < n; i++) {
8850 if (!locked) {
8851 _request_list_mutex.lock();
8852 locked = true;
8853 }
8855 if (r.buffer_handle != buffer_handle)
8856 continue;
8857 if (!bm_match_event(r.event_id, r.trigger_mask, pevent))
8858 continue;
8859 /* must release the lock on the request list: user provided r.dispatcher() can add or remove event requests, and we will deadlock. K.O. */
8860 _request_list_mutex.unlock();
8861 locked = false;
8862 /* if event is fragmented, call defragmenter */
8863 if (((uint16_t(pevent->event_id) & uint16_t(0xF000)) == uint16_t(EVENTID_FRAG1)) || ((uint16_t(pevent->event_id) & uint16_t(0xF000)) == uint16_t(EVENTID_FRAG))) {
8864 bm_defragment_event(buffer_handle, i, pevent, (void *) (pevent + 1), r.dispatcher);
8865 } else {
8866 r.dispatcher(buffer_handle, i, pevent, (void *) (pevent + 1));
8867 }
8868 }
8869 if (locked)
8870 _request_list_mutex.unlock();
8871}
static void bm_defragment_event(HNDLE buffer_handle, HNDLE request_id, EVENT_HEADER *pevent, void *pdata, EVENT_HANDLER *dispatcher)
Definition midas.cxx:11432
DWORD n[4]
Definition mana.cxx:247
#define EVENTID_FRAG
Definition midas.h:908
#define EVENTID_FRAG1
Definition midas.h:907
short int event_id
Definition midas.cxx:206
INT buffer_handle
Definition midas.cxx:205
short int trigger_mask
Definition midas.cxx:207
EVENT_HANDLER * dispatcher
Definition midas.cxx:208
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_empty_buffers()

INT bm_empty_buffers ( void  )

Clears event buffer and cache. If an event buffer is large and a consumer is slow in analyzing events, events are usually received some time after they are produced. This effect is even more experienced if a read cache is used (via bm_set_cache_size()). When changes to the hardware are made in the experience, the consumer will then still analyze old events before any new event which reflects the hardware change. Users can be fooled by looking at histograms which reflect the hardware change many seconds after they have been made.

To overcome this potential problem, the analyzer can call bm_empty_buffers() just after the hardware change has been made which skips all old events contained in event buffers and read caches. Technically this is done by forwarding the read pointer of the client. No events are really deleted, they are still visible to other clients like the logger.

Note that the front-end also contains write buffers which can delay the delivery of events. The standard front-end framework mfe.c reduces this effect by flushing all buffers once every second.

Returns
BM_SUCCESS

Definition at line 11388 of file midas.cxx.

11388 {
11389 if (rpc_is_remote())
11391
11392#ifdef LOCAL_ROUTINES
11393 {
11394 std::vector<BUFFER*> mybuffers;
11395
11396 gBuffersMutex.lock();
11397 mybuffers = gBuffers;
11398 gBuffersMutex.unlock();
11399
11400 /* go through all buffers */
11401 for (BUFFER* pbuf : mybuffers) {
11402 if (!pbuf)
11403 continue;
11404 if (!pbuf->attached)
11405 continue;
11406
11407 int status = bm_skip_event(pbuf);
11408 if (status != BM_SUCCESS)
11409 return status;
11410 }
11411 }
11412#endif /* LOCAL_ROUTINES */
11413
11414 return BM_SUCCESS;
11415}
static int bm_skip_event(BUFFER *pbuf)
Definition midas.cxx:10981
#define RPC_BM_EMPTY_BUFFERS
Definition mrpc.h:49
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_fill_read_cache_locked()

static int bm_fill_read_cache_locked ( bm_lock_buffer_guard pbuf_guard,
int  timeout_msec 
)
static

Definition at line 9012 of file midas.cxx.

9013{
9014 BUFFER* pbuf = pbuf_guard.get_pbuf();
9015 BUFFER_HEADER* pheader = pbuf->buffer_header;
9016 BUFFER_CLIENT *pc = bm_get_my_client_locked(pbuf_guard);
9017 BOOL need_wakeup = FALSE;
9018
9019 //printf("bm_fill_read_cache: [%s] timeout %d, size %d, rp %d, wp %d\n", pheader->name, timeout_msec, pbuf->read_cache_size, pbuf->read_cache_rp, pbuf->read_cache_wp);
9020
9021 /* loop over all events in the buffer */
9022
9023 while (1) {
9024 EVENT_HEADER *pevent = NULL;
9025 int event_size = 3; // poison value
9026 int total_size = 3; // poison value
9027
9028 int status = bm_peek_buffer_locked(pbuf, pheader, pc, &pevent, &event_size, &total_size);
9029 if (status == BM_CORRUPTED) {
9030 return status;
9031 } else if (status != BM_SUCCESS) {
9032 /* event buffer is empty */
9033 if (timeout_msec == BM_NO_WAIT) {
9034 if (need_wakeup)
9035 bm_wakeup_producers_locked(pheader, pc);
9036 if (pbuf->read_cache_rp == pbuf->read_cache_wp) {
9037 // read cache is empty
9038 return BM_ASYNC_RETURN;
9039 }
9040 return BM_SUCCESS;
9041 }
9042
9043 int status = bm_wait_for_more_events_locked(pbuf_guard, pc, timeout_msec, TRUE);
9044
9045 if (status != BM_SUCCESS) {
9046 // we only come here with SS_ABORT & co
9047 return status;
9048 }
9049
9050 // make sure we wait for new event only once
9051 timeout_msec = BM_NO_WAIT;
9052 // go back to bm_peek_buffer_locked
9053 continue;
9054 }
9055
9056 /* loop over all requests: if this event matches a request,
9057 * copy it to the read cache */
9058
9059 BOOL is_requested = bm_check_requests(pc, pevent);
9060
9061 if (is_requested) {
9062 if (pbuf->read_cache_wp + total_size > pbuf->read_cache_size) {
9063 /* read cache is full */
9064 if (need_wakeup)
9065 bm_wakeup_producers_locked(pheader, pc);
9066 return BM_SUCCESS;
9067 }
9068
9070
9071 pbuf->read_cache_wp += total_size;
9072
9073 /* update statistics */
9074 pheader->num_out_events++;
9075 pbuf->count_read++;
9076 pbuf->bytes_read += event_size;
9077 }
9078
9079 /* shift read pointer */
9080
9081 int new_read_pointer = bm_incr_rp_no_check(pheader, pc->read_pointer, total_size);
9082 pc->read_pointer = new_read_pointer;
9083
9084 need_wakeup = TRUE;
9085 }
9086 /* NOT REACHED */
9087}
BUFFER * get_pbuf() const
Definition midas.cxx:3197
static void bm_wakeup_producers_locked(const BUFFER_HEADER *pheader, const BUFFER_CLIENT *pc)
Definition midas.cxx:8807
static int bm_incr_rp_no_check(const BUFFER_HEADER *pheader, int rp, int total_size)
Definition midas.cxx:6241
static BOOL bm_check_requests(const BUFFER_CLIENT *pc, const EVENT_HEADER *pevent)
Definition midas.cxx:8986
static void bm_read_from_buffer_locked(const BUFFER_HEADER *pheader, int rp, char *buf, int event_size)
Definition midas.cxx:8956
static int bm_peek_buffer_locked(BUFFER *pbuf, BUFFER_HEADER *pheader, BUFFER_CLIENT *pc, EVENT_HEADER **ppevent, int *pevent_size, int *ptotal_size)
Definition midas.cxx:8911
static int bm_wait_for_more_events_locked(bm_lock_buffer_guard &pbuf_guard, BUFFER_CLIENT *pc, int timeout_msec, BOOL unlock_read_cache)
Definition midas.cxx:9412
#define BM_ASYNC_RETURN
Definition midas.h:613
#define BM_NO_WAIT
Definition midas.h:366
int event_size
Definition msysmon.cxx:527
INT read_pointer
Definition midas.h:941
INT num_out_events
Definition midas.h:966
double bytes_read
Definition midas.h:1022
int count_read
Definition midas.h:1021
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_find_first_request_locked()

static int bm_find_first_request_locked ( BUFFER_CLIENT pc,
const EVENT_HEADER pevent 
)
static

Definition at line 9609 of file midas.cxx.

9609 {
9610 if (pc->pid) {
9611 int j;
9612 for (j = 0; j < pc->max_request_index; j++) {
9613 const EVENT_REQUEST *prequest = pc->event_request + j;
9614 if (prequest->valid && bm_match_event(prequest->event_id, prequest->trigger_mask, pevent)) {
9615 return prequest->id;
9616 }
9617 }
9618 }
9619
9620 return -1;
9621}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_flush_cache()

INT bm_flush_cache ( int  buffer_handle,
int  timeout_msec 
)

Definition at line 10242 of file midas.cxx.

10243{
10244 if (rpc_is_remote()) {
10245 return bm_flush_cache_rpc(buffer_handle, timeout_msec);
10246 }
10247
10248#ifdef LOCAL_ROUTINES
10249 {
10250 INT status = 0;
10251
10252 //printf("bm_flush_cache!\n");
10253
10254 BUFFER *pbuf = bm_get_buffer("bm_flush_cache", buffer_handle, &status);
10255
10256 if (!pbuf)
10257 return status;
10258
10259 if (pbuf->write_cache_size == 0)
10260 return BM_SUCCESS;
10261
10263
10264 if (status != BM_SUCCESS)
10265 return status;
10266
10267 /* check if anything needs to be flushed */
10268 if (pbuf->write_cache_wp == 0) {
10269 pbuf->write_cache_mutex.unlock();
10270 return BM_SUCCESS;
10271 }
10272
10273 /* lock the buffer */
10274 bm_lock_buffer_guard pbuf_guard(pbuf);
10275
10276 if (!pbuf_guard.is_locked())
10277 return pbuf_guard.get_status();
10278
10279 status = bm_flush_cache_locked(pbuf_guard, timeout_msec);
10280
10281 /* unlock in correct order */
10282
10283 if (pbuf_guard.is_locked()) {
10284 // check if bm_wait_for_free_space() failed to relock the buffer
10285 pbuf_guard.unlock();
10286 }
10287
10288 pbuf->write_cache_mutex.unlock();
10289
10290 return status;
10291 }
10292#endif /* LOCAL_ROUTINES */
10293
10294 return BM_SUCCESS;
10295}
static int bm_flush_cache_rpc(int buffer_handle, int timeout_msec)
Definition midas.cxx:10007
static INT bm_flush_cache_locked(bm_lock_buffer_guard &pbuf_guard, int timeout_msec)
Definition midas.cxx:10098
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_flush_cache_locked()

static INT bm_flush_cache_locked ( bm_lock_buffer_guard pbuf_guard,
int  timeout_msec 
)
static

Empty write cache. This function should be used if events in the write cache should be visible to the consumers immediately. It should be called at the end of each run, otherwise events could be kept in the write buffer and will flow to the data of the next run.

Parameters
buffer_handleBuffer handle obtained via bm_open_buffer() or 0 to flush data in the mserver event socket
timeout_msecTimeout waiting for free space in the event buffer. If BM_WAIT, wait forever. If BM_NO_WAIT, the function returns immediately with a value of BM_ASYNC_RETURN without writing the cache.
Returns
BM_SUCCESS, BM_INVALID_HANDLE
BM_ASYNC_RETURN Routine called with async_flag == BM_NO_WAIT and buffer has not enough space to receive cache
BM_NO_MEMORY Event is too large for network buffer or event buffer. One has to increase the event buffer size "/Experiment/Buffer sizes/SYSTEM" and/or /Experiment/MAX_EVENT_SIZE in ODB.

Definition at line 10098 of file midas.cxx.

10099{
10100 // NB we come here with write cache locked and buffer locked.
10101
10102 {
10103 INT status = 0;
10104
10105 //printf("bm_flush_cache_locked!\n");
10106
10107 BUFFER* pbuf = pbuf_guard.get_pbuf();
10108 BUFFER_HEADER* pheader = pbuf->buffer_header;
10109
10110 //printf("bm_flush_cache_locked: buffer %s, cache rp %zu, wp %zu, timeout %d msec\n", pbuf->buffer_name, pbuf->write_cache_rp, pbuf->write_cache_wp, timeout_msec);
10111
10112 int old_write_pointer = pheader->write_pointer;
10113
10114 int request_id[MAX_CLIENTS];
10115 for (int i = 0; i < pheader->max_client_index; i++) {
10116 request_id[i] = -1;
10117 }
10118
10119 size_t ask_rp = pbuf->write_cache_rp;
10120 size_t ask_wp = pbuf->write_cache_wp;
10121
10122 if (ask_wp == 0) { // nothing to do
10123 return BM_SUCCESS;
10124 }
10125
10126 if (ask_rp == ask_wp) { // nothing to do
10127 return BM_SUCCESS;
10128 }
10129
10130 assert(ask_rp < ask_wp);
10131
10132 size_t ask_free = ALIGN8(ask_wp - ask_rp);
10133
10134 if (ask_free == 0) { // nothing to do
10135 return BM_SUCCESS;
10136 }
10137
10138#if 0
10140 if (status != BM_SUCCESS) {
10141 printf("bm_flush_cache: corrupted 111!\n");
10142 abort();
10143 }
10144#endif
10145
10146 status = bm_wait_for_free_space_locked(pbuf_guard, timeout_msec, ask_free, true);
10147
10148 if (status != BM_SUCCESS) {
10149 return status;
10150 }
10151
10152 // NB: ask_rp, ask_wp and ask_free are invalid after calling bm_wait_for_free_space():
10153 //
10154 // wait_for_free_space() will sleep with all locks released,
10155 // during this time, another thread may call bm_send_event() that will
10156 // add one or more events to the write cache and after wait_for_free_space()
10157 // returns, size of data in cache will be bigger than the amount
10158 // of free space we requested. so we need to keep track of how
10159 // much data we write to the buffer and ask for more data
10160 // if we run short. This is the reason for the big loop
10161 // around wait_for_free_space(). We ask for slightly too little free
10162 // space to make sure all this code is always used and does work. K.O.
10163
10164 if (pbuf->write_cache_wp == 0) {
10165 /* somebody emptied the cache while we were inside bm_wait_for_free_space */
10166 return BM_SUCCESS;
10167 }
10168
10169 //size_t written = 0;
10170 while (pbuf->write_cache_rp < pbuf->write_cache_wp) {
10171 /* loop over all events in cache */
10172
10173 const EVENT_HEADER *pevent = (const EVENT_HEADER *) (pbuf->write_cache + pbuf->write_cache_rp);
10174 size_t event_size = (pevent->data_size + sizeof(EVENT_HEADER));
10175 size_t total_size = ALIGN8(event_size);
10176
10177#if 0
10178 printf("bm_flush_cache: cache size %d, wp %d, rp %d, event data_size %d, event_size %d, total_size %d, free %d, written %d\n",
10179 int(pbuf->write_cache_size),
10180 int(pbuf->write_cache_wp),
10181 int(pbuf->write_cache_rp),
10182 int(pevent->data_size),
10183 int(event_size),
10184 int(total_size),
10185 int(ask_free),
10186 int(written));
10187#endif
10188
10189 // check for crazy event size
10190 assert(total_size >= sizeof(EVENT_HEADER));
10191 assert(total_size <= (size_t)pheader->size);
10192
10193 bm_write_to_buffer_locked(pheader, 1, (char**)&pevent, &event_size, total_size);
10194
10195 /* update statistics */
10196 pheader->num_in_events++;
10197 pbuf->count_sent += 1;
10198 pbuf->bytes_sent += total_size;
10199
10200 /* see comment for the same code in bm_send_event().
10201 * We make sure the buffer is never 100% full */
10202 assert(pheader->write_pointer != pheader->read_pointer);
10203
10204 /* check if anybody has a request for this event */
10205 for (int i = 0; i < pheader->max_client_index; i++) {
10206 BUFFER_CLIENT *pc = pheader->client + i;
10207 int r = bm_find_first_request_locked(pc, pevent);
10208 if (r >= 0) {
10209 request_id[i] = r;
10210 }
10211 }
10212
10213 /* this loop does not loop forever because rp
10214 * is monotonously incremented here. write_cache_wp does
10215 * not change */
10216
10217 pbuf->write_cache_rp += total_size;
10218 //written += total_size;
10219
10220 assert(pbuf->write_cache_rp > 0);
10221 assert(pbuf->write_cache_rp <= pbuf->write_cache_size);
10222 assert(pbuf->write_cache_rp <= pbuf->write_cache_wp);
10223 }
10224
10225 /* the write cache is now empty */
10226 assert(pbuf->write_cache_wp == pbuf->write_cache_rp);
10227 pbuf->write_cache_wp = 0;
10228 pbuf->write_cache_rp = 0;
10229
10230 /* check which clients are waiting */
10231 for (int i = 0; i < pheader->max_client_index; i++) {
10232 BUFFER_CLIENT *pc = pheader->client + i;
10233 bm_notify_reader_locked(pheader, pc, old_write_pointer, request_id[i]);
10234 }
10235 }
10236
10237 return BM_SUCCESS;
10238}
static void bm_notify_reader_locked(BUFFER_HEADER *pheader, BUFFER_CLIENT *pc, int old_write_pointer, int request_id)
Definition midas.cxx:9623
static int bm_find_first_request_locked(BUFFER_CLIENT *pc, const EVENT_HEADER *pevent)
Definition midas.cxx:9609
static int bm_validate_buffer_locked(const BUFFER *pbuf)
Definition midas.cxx:6325
static void bm_write_to_buffer_locked(BUFFER_HEADER *pheader, int sg_n, const char *const sg_ptr[], const size_t sg_len[], size_t total_size)
Definition midas.cxx:9524
static int bm_wait_for_free_space_locked(bm_lock_buffer_guard &pbuf_guard, int timeout_msec, int requested_space, bool unlock_write_cache)
Definition midas.cxx:9100
#define ALIGN8(x)
Definition midas.h:522
INT num_in_events
Definition midas.h:965
INT write_pointer
Definition midas.h:964
INT read_pointer
Definition midas.h:963
int count_sent
Definition midas.h:1013
double bytes_sent
Definition midas.h:1014
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_flush_cache_rpc()

static int bm_flush_cache_rpc ( int  buffer_handle,
int  timeout_msec 
)
static

Definition at line 10007 of file midas.cxx.

10008{
10009 //printf("bm_flush_cache_rpc: handle %d, timeout %d\n", buffer_handle, timeout_msec);
10010
10011 DWORD time_start = ss_millitime();
10012 DWORD time_end = time_start + timeout_msec;
10013 DWORD time_bombout = time_end;
10014
10015 if (timeout_msec < 10000)
10016 time_bombout = time_start + 10000; // 10 seconds
10017
10018 int xtimeout_msec = timeout_msec;
10019
10020 while (1) {
10021 if (timeout_msec == BM_WAIT) {
10022 xtimeout_msec = 1000;
10023 } else if (timeout_msec == BM_NO_WAIT) {
10024 xtimeout_msec = BM_NO_WAIT;
10025 } else {
10026 if (xtimeout_msec > 1000) {
10027 xtimeout_msec = 1000;
10028 }
10029 }
10030
10031 int status = rpc_call(RPC_BM_FLUSH_CACHE, buffer_handle, xtimeout_msec);
10032
10033 //printf("bm_flush_cache_rpc: handle %d, timeout %d, status %d\n", buffer_handle, xtimeout_msec, status);
10034
10035 if (status == BM_ASYNC_RETURN) {
10036 if (timeout_msec == BM_WAIT) {
10037 DWORD now = ss_millitime();
10038 if (now >= time_bombout) {
10039 // timeout
10040 return BM_TIMEOUT;
10041 }
10042
10043 // BM_WAIT means wait forever
10044 continue;
10045 } else if (timeout_msec == BM_NO_WAIT) {
10046 // BM_NO_WAIT means do not wait
10047 return status;
10048 } else {
10049 DWORD now = ss_millitime();
10050 if (now >= time_end) {
10051 // timeout, return BM_ASYNC_RETURN
10052 return status;
10053 }
10054
10055 DWORD remain = time_end - now;
10056
10057 if (remain < (DWORD)xtimeout_msec) {
10058 xtimeout_msec = remain;
10059 }
10060
10061 if (now >= time_bombout) {
10062 // timeout
10063 return BM_TIMEOUT;
10064 }
10065
10066 // keep asking for event...
10067 continue;
10068 }
10069 } else if (status == BM_SUCCESS) {
10070 // success, return BM_SUCCESS
10071 return status;
10072 } else {
10073 // error
10074 return status;
10075 }
10076 }
10077}
#define BM_TIMEOUT
Definition midas.h:625
#define BM_WAIT
Definition midas.h:365
#define RPC_BM_FLUSH_CACHE
Definition mrpc.h:46
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_get_buffer_handle()

INT bm_get_buffer_handle ( const char *  buffer_name,
INT buffer_handle 
)

If buffer is already open, return it's handle

Parameters
buffer_namebuffer name
Returns
BM_SUCCESS, BM_NOT_FOUND

Definition at line 7095 of file midas.cxx.

7096{
7097 gBuffersMutex.lock();
7098 for (size_t i = 0; i < gBuffers.size(); i++) {
7099 BUFFER* pbuf = gBuffers[i];
7100 if (pbuf && pbuf->attached && equal_ustring(pbuf->buffer_name, buffer_name)) {
7101 *buffer_handle = i + 1;
7102 gBuffersMutex.unlock();
7103 return BM_SUCCESS;
7104 }
7105 }
7106 gBuffersMutex.unlock();
7107 return BM_NOT_FOUND;
7108}
#define BM_NOT_FOUND
Definition midas.h:612
BOOL equal_ustring(const char *str1, const char *str2)
Definition odb.cxx:3780
char buffer_name[NAME_LENGTH]
Definition mevb.cxx:45
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_incr_read_cache_locked()

static void bm_incr_read_cache_locked ( BUFFER pbuf,
int  total_size 
)
static

Definition at line 8875 of file midas.cxx.

8875 {
8876 /* increment read cache read pointer */
8877 pbuf->read_cache_rp += total_size;
8878
8879 if (pbuf->read_cache_rp == pbuf->read_cache_wp) {
8880 pbuf->read_cache_rp = 0;
8881 pbuf->read_cache_wp = 0;
8882 }
8883}
Here is the caller graph for this function:

◆ bm_incr_rp_no_check()

static int bm_incr_rp_no_check ( const BUFFER_HEADER pheader,
int  rp,
int  total_size 
)
static

Definition at line 6241 of file midas.cxx.

6242{
6243#if 0
6244 if (gRpLog == NULL) {
6245 gRpLog = fopen("rp.log", "a");
6246 }
6247 if (gRpLog && (total_size < 16)) {
6248 const char *pdata = (const char *) (pheader + 1);
6249 const DWORD *pevent = (const DWORD*) (pdata + rp);
6250 fprintf(gRpLog, "%s: rp %d, total_size %d, at rp 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", pheader->name, rp, total_size,
6251 pevent[0], pevent[1], pevent[2], pevent[3], pevent[4], pevent[5]);
6252 }
6253#endif
6254
6255 // these checks are already done before we come here.
6256 // but we check again as last-ressort protection. K.O.
6257 assert(total_size > 0);
6258 assert(total_size >= (int)sizeof(EVENT_HEADER));
6259
6260 rp += total_size;
6261 if (rp >= pheader->size) {
6262 rp -= pheader->size;
6263 } else if ((rp + (int) sizeof(EVENT_HEADER)) > pheader->size) {
6264 // note: ">" here to match bm_write_to_buffer_locked() and bm_validate_rp().
6265 // if at the end of the buffer, the remaining free space is exactly
6266 // equal to the size of an event header, the event header
6267 // is written there, the pointer is wrapped and the event data
6268 // is written to the beginning of the buffer.
6269 rp = 0;
6270 }
6271 return rp;
6272}
Here is the caller graph for this function:

◆ bm_match_event()

INT bm_match_event ( short int  event_id,
short int  trigger_mask,
const EVENT_HEADER pevent 
)

Check if an event matches a given event request by the event id and trigger mask

Parameters
event_idEvent ID of request
trigger_maskTrigger mask of request
peventPointer to event to check
Returns
TRUE if event matches request

Definition at line 6033 of file midas.cxx.

6033 {
6034 // NB: cast everything to unsigned 16 bit to avoid bitwise comparison failure
6035 // because of mismatch in sign-extension between signed 16-bit event_id and
6036 // unsigned 16-bit constants. K.O.
6037
6038 if (((uint16_t(pevent->event_id) & uint16_t(0xF000)) == uint16_t(EVENTID_FRAG1)) || ((uint16_t(pevent->event_id) & uint16_t(0xF000)) == uint16_t(EVENTID_FRAG)))
6039 /* fragmented event */
6040 return (((uint16_t(event_id) == uint16_t(EVENTID_ALL)) || (uint16_t(event_id) == (uint16_t(pevent->event_id) & uint16_t(0x0FFF))))
6041 && ((uint16_t(trigger_mask) == uint16_t(TRIGGER_ALL)) || ((uint16_t(trigger_mask) & uint16_t(pevent->trigger_mask)))));
6042
6043 return (((uint16_t(event_id) == uint16_t(EVENTID_ALL)) || (uint16_t(event_id) == uint16_t(pevent->event_id)))
6044 && ((uint16_t(trigger_mask) == uint16_t(TRIGGER_ALL)) || ((uint16_t(trigger_mask) & uint16_t(pevent->trigger_mask)))));
6045}
#define TRIGGER_ALL
Definition midas.h:538
#define EVENTID_ALL
Definition midas.h:537
Here is the caller graph for this function:

◆ bm_next_rp()

static int bm_next_rp ( const char *  who,
const BUFFER_HEADER pheader,
const char *  pdata,
int  rp 
)
static

Definition at line 6274 of file midas.cxx.

6274 {
6275 const EVENT_HEADER *pevent = (const EVENT_HEADER *) (pdata + rp);
6276 int event_size = pevent->data_size + sizeof(EVENT_HEADER);
6277 int total_size = ALIGN8(event_size);
6278
6279 if (pevent->data_size <= 0 || total_size <= 0 || total_size > pheader->size) {
6280 cm_msg(MERROR, "bm_next_rp",
6281 "error: buffer \"%s\" is corrupted: rp %d points to an invalid event: data_size %d, event size %d, total_size %d, buffer read_pointer %d, write_pointer %d, size %d, called from %s",
6282 pheader->name,
6283 rp,
6284 pevent->data_size,
6285 event_size,
6286 total_size,
6287 pheader->read_pointer,
6288 pheader->write_pointer,
6289 pheader->size,
6290 who);
6291 return -1;
6292 }
6293
6294 int remaining = 0;
6295 if (rp < pheader->write_pointer) {
6296 remaining = pheader->write_pointer - rp;
6297 } else {
6298 remaining = pheader->size - rp;
6299 remaining += pheader->write_pointer;
6300 }
6301
6302 //printf("bm_next_rp: total_size %d, remaining %d, rp %d, wp %d, size %d\n", total_size, remaining, rp, pheader->write_pointer, pheader->size);
6303
6304 if (total_size > remaining) {
6305 cm_msg(MERROR, "bm_next_rp",
6306 "error: buffer \"%s\" is corrupted: rp %d points to an invalid event: data_size %d, event size %d, total_size %d, buffer read_pointer %d, write_pointer %d, size %d, remaining %d, called from %s",
6307 pheader->name,
6308 rp,
6309 pevent->data_size,
6310 event_size,
6311 total_size,
6312 pheader->read_pointer,
6313 pheader->write_pointer,
6314 pheader->size,
6315 remaining,
6316 who);
6317 return -1;
6318 }
6319
6320 rp = bm_incr_rp_no_check(pheader, rp, total_size);
6321
6322 return rp;
6323}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_notify_reader_locked()

static void bm_notify_reader_locked ( BUFFER_HEADER pheader,
BUFFER_CLIENT pc,
int  old_write_pointer,
int  request_id 
)
static

Definition at line 9623 of file midas.cxx.

9623 {
9624 if (request_id >= 0) {
9625 /* if that client has a request and is suspended, wake it up */
9626 if (pc->read_wait) {
9627 char str[80];
9628 sprintf(str, "B %s %d", pheader->name, request_id);
9629 ss_resume(pc->port, str);
9630 //printf("bm_notify_reader_locked: buffer [%s] client [%s] request_id %d, port %d, message [%s]\n", pheader->name, pc->name, request_id, pc->port, str);
9631 //printf("bm_notify_reader_locked: buffer [%s] client [%s] clear read_wait!\n", pheader->name, pc->name);
9632 pc->read_wait = FALSE;
9633 }
9634 }
9635}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_open_buffer()

INT bm_open_buffer ( const char *  buffer_name,
INT  buffer_size,
INT buffer_handle 
)

Open an event buffer. Two default buffers are created by the system. The "SYSTEM" buffer is used to exchange events and the "SYSMSG" buffer is used to exchange system messages. The name and size of the event buffers is defined in midas.h as EVENT_BUFFER_NAME and DEFAULT_BUFFER_SIZE. Following example opens the "SYSTEM" buffer, requests events with ID 1 and enters a main loop. Events are then received in process_event()

#include <stdio.h>
#include "midas.h"
void process_event(HNDLE hbuf, HNDLE request_id, EVENT_HEADER *pheader, void *pevent)
{
printf("Received event #%d\r",
pheader->serial_number);
}
{
INT status, request_id;
HNDLE hbuf;
status = cm_connect_experiment("pc810", "Sample", "Simple Analyzer", NULL);
return 1;
do
{
status = cm_yield(1000);
} while (status != RPC_SHUTDOWN && status != SS_ABORT);
return 0;
}
INT bm_open_buffer(const char *buffer_name, INT buffer_size, INT *buffer_handle)
Definition midas.cxx:6728
INT bm_request_event(HNDLE buffer_handle, short int event_id, short int trigger_mask, INT sampling_type, HNDLE *request_id, EVENT_HANDLER *func)
Definition midas.cxx:8485
INT cm_yield(INT millisec)
Definition midas.cxx:5660
INT cm_connect_experiment(const char *host_name, const char *exp_name, const char *client_name, void(*func)(char *))
Definition midas.cxx:2294
INT cm_disconnect_experiment(void)
Definition midas.cxx:2862
#define CM_SUCCESS
Definition midas.h:582
#define SS_ABORT
Definition midas.h:678
#define RPC_SHUTDOWN
Definition midas.h:708
int main()
Definition hwtest.cxx:23
INT process_event(ANALYZE_REQUEST *par, EVENT_HEADER *pevent)
Definition mana.cxx:3081
#define DEFAULT_BUFFER_SIZE
Definition midas.h:255
#define EVENT_BUFFER_NAME
Definition midas.h:269
Parameters
buffer_nameName of buffer
buffer_sizeDefault size of buffer in bytes. Can by overwritten with ODB value
buffer_handleBuffer handle returned by function
Returns
BM_SUCCESS, BM_CREATED
BM_NO_SHM Shared memory cannot be created
BM_NO_SEMAPHORE Semaphore cannot be created
BM_NO_MEMORY Not enough memory to create buffer descriptor
BM_MEMSIZE_MISMATCH Buffer size conflicts with an existing buffer of different size
BM_INVALID_PARAM Invalid parameter

Definition at line 6728 of file midas.cxx.

6728 {
6729 INT status;
6730
6731 if (rpc_is_remote()) {
6732 status = rpc_call(RPC_BM_OPEN_BUFFER, buffer_name, buffer_size, buffer_handle);
6733
6734 HNDLE hDB;
6736 if (status != SUCCESS || hDB == 0) {
6737 cm_msg(MERROR, "bm_open_buffer", "cannot open buffer \'%s\' - not connected to ODB", buffer_name);
6738 return BM_NO_SHM;
6739 }
6740
6742
6743 int size = sizeof(INT);
6744 status = db_get_value(hDB, 0, "/Experiment/MAX_EVENT_SIZE", &_bm_max_event_size, &size, TID_UINT32, TRUE);
6745
6746 if (status != DB_SUCCESS) {
6747 cm_msg(MERROR, "bm_open_buffer", "Cannot get ODB /Experiment/MAX_EVENT_SIZE, db_get_value() status %d",
6748 status);
6749 return status;
6750 }
6751
6752 return status;
6753 }
6754#ifdef LOCAL_ROUTINES
6755 {
6756 HNDLE shm_handle;
6757 size_t shm_size;
6758 HNDLE hDB;
6759 const int max_buffer_size = 2 * 1000 * 1024 * 1024; // limited by 32-bit integers in the buffer header
6760
6761 bm_cleanup("bm_open_buffer", ss_millitime(), FALSE);
6762
6763 if (!buffer_name || !buffer_name[0]) {
6764 cm_msg(MERROR, "bm_open_buffer", "cannot open buffer with zero name");
6765 return BM_INVALID_PARAM;
6766 }
6767
6768 if (strlen(buffer_name) >= NAME_LENGTH) {
6769 cm_msg(MERROR, "bm_open_buffer", "buffer name \"%s\" is longer than %d bytes", buffer_name, NAME_LENGTH);
6770 return BM_INVALID_PARAM;
6771 }
6772
6774
6775 if (status != SUCCESS || hDB == 0) {
6776 //cm_msg(MERROR, "bm_open_buffer", "cannot open buffer \'%s\' - not connected to ODB", buffer_name);
6777 return BM_NO_SHM;
6778 }
6779
6780 /* get buffer size from ODB, user parameter as default if not present in ODB */
6781 std::string odb_path;
6782 odb_path += "/Experiment/Buffer sizes/";
6783 odb_path += buffer_name;
6784
6785 int size = sizeof(INT);
6786 status = db_get_value(hDB, 0, odb_path.c_str(), &buffer_size, &size, TID_UINT32, TRUE);
6787
6788 if (buffer_size <= 0 || buffer_size > max_buffer_size) {
6789 cm_msg(MERROR, "bm_open_buffer",
6790 "Cannot open buffer \"%s\", invalid buffer size %d in ODB \"%s\", maximum buffer size is %d",
6791 buffer_name, buffer_size, odb_path.c_str(), max_buffer_size);
6792
6793 // special kludge for "SYSMSG": if ODB has wrong data for the buffer size, odbedit cannot start and we cannot cannot fix it. K.O. 17 Jul 2026
6794
6795 if (strcmp(buffer_name, MESSAGE_BUFFER_NAME) != 0)
6796 return BM_INVALID_PARAM;
6797
6798 cm_msg(MERROR, "bm_open_buffer",
6799 "Will use default SYSMSG buffer size %d to open buffer \"%s\"",
6801 buffer_size = MESSAGE_BUFFER_SIZE;
6802 }
6803
6805
6806 size = sizeof(INT);
6807 status = db_get_value(hDB, 0, "/Experiment/MAX_EVENT_SIZE", &_bm_max_event_size, &size, TID_UINT32, TRUE);
6808
6809 if (status != DB_SUCCESS) {
6810 cm_msg(MERROR, "bm_open_buffer", "Cannot get ODB /Experiment/MAX_EVENT_SIZE, db_get_value() status %d",
6811 status);
6812 return status;
6813 }
6814
6815 /* check if buffer already is open */
6816 gBuffersMutex.lock();
6817 for (size_t i = 0; i < gBuffers.size(); i++) {
6818 BUFFER* pbuf = gBuffers[i];
6819 if (pbuf && pbuf->attached && equal_ustring(pbuf->buffer_name, buffer_name)) {
6820 *buffer_handle = i + 1;
6821 gBuffersMutex.unlock();
6822 return BM_SUCCESS;
6823 }
6824 }
6825 gBuffersMutex.unlock();
6826
6827 // only one thread at a time should create new buffers
6828
6829 static std::mutex gNewBufferMutex;
6830 std::lock_guard<std::mutex> guard(gNewBufferMutex);
6831
6832 // if we had a race against another thread
6833 // and while we were waiting for gNewBufferMutex
6834 // the other thread created this buffer, we return it.
6835
6836 gBuffersMutex.lock();
6837 for (size_t i = 0; i < gBuffers.size(); i++) {
6838 BUFFER* pbuf = gBuffers[i];
6839 if (pbuf && pbuf->attached && equal_ustring(pbuf->buffer_name, buffer_name)) {
6840 *buffer_handle = i + 1;
6841 gBuffersMutex.unlock();
6842 return BM_SUCCESS;
6843 }
6844 }
6845 gBuffersMutex.unlock();
6846
6847 /* allocate new BUFFER object */
6848
6849 BUFFER* pbuf = new BUFFER;
6850
6851 /* there is no constructor for BUFFER object, we have to zero the arrays manually */
6852
6853 for (int i=0; i<MAX_CLIENTS; i++) {
6854 pbuf->client_count_write_wait[i] = 0;
6855 pbuf->client_time_write_wait[i] = 0;
6856 }
6857
6858 /* create buffer semaphore */
6859
6861
6862 if (status != SS_CREATED && status != SS_SUCCESS) {
6863 *buffer_handle = 0;
6864 delete pbuf;
6865 return BM_NO_SEMAPHORE;
6866 }
6867
6868 std::string client_name = cm_get_client_name();
6869
6870 /* store client name */
6871 mstrlcpy(pbuf->client_name, client_name.c_str(), sizeof(pbuf->client_name));
6872
6873 /* store buffer name */
6874 mstrlcpy(pbuf->buffer_name, buffer_name, sizeof(pbuf->buffer_name));
6875
6876 /* lock buffer semaphore to avoid race with bm_open_buffer() in a different program */
6877
6878 pbuf->attached = true; // required by bm_lock_buffer()
6879
6880 bm_lock_buffer_guard pbuf_guard(pbuf);
6881
6882 if (!pbuf_guard.is_locked()) {
6883 // cannot happen, no other thread can see this pbuf
6884 abort();
6885 return BM_NO_SEMAPHORE;
6886 }
6887
6888 /* open shared memory */
6889
6890 void *p = NULL;
6891 status = ss_shm_open(buffer_name, sizeof(BUFFER_HEADER) + buffer_size, &p, &shm_size, &shm_handle, FALSE);
6892
6893 if (status != SS_SUCCESS && status != SS_CREATED) {
6894 *buffer_handle = 0;
6895 pbuf_guard.unlock();
6896 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
6897 delete pbuf;
6898 return BM_NO_SHM;
6899 }
6900
6901 pbuf->buffer_header = (BUFFER_HEADER *) p;
6902
6903 BUFFER_HEADER *pheader = pbuf->buffer_header;
6904
6905 bool shm_created = (status == SS_CREATED);
6906
6907 if (shm_created) {
6908 /* initialize newly created shared memory */
6909
6910 memset(pheader, 0, sizeof(BUFFER_HEADER) + buffer_size);
6911
6912 mstrlcpy(pheader->name, buffer_name, sizeof(pheader->name));
6913 pheader->size = buffer_size;
6914
6915 } else {
6916 /* validate existing shared memory */
6917
6918 if (!equal_ustring(pheader->name, buffer_name)) {
6919 // unlock before calling cm_msg(). if we are SYSMSG, we wil ldeadlock. K.O.
6920 pbuf_guard.unlock();
6921 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
6922 cm_msg(MERROR, "bm_open_buffer",
6923 "Buffer \"%s\" is corrupted, mismatch of buffer name in shared memory \"%s\"", buffer_name,
6924 pheader->name);
6925 *buffer_handle = 0;
6926 delete pbuf;
6927 return BM_CORRUPTED;
6928 }
6929
6930 if ((pheader->num_clients < 0) || (pheader->num_clients > MAX_CLIENTS)) {
6931 // unlock before calling cm_msg(). if we are SYSMSG, we wil ldeadlock. K.O.
6932 pbuf_guard.unlock();
6933 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
6934 cm_msg(MERROR, "bm_open_buffer", "Buffer \"%s\" is corrupted, num_clients %d exceeds MAX_CLIENTS %d",
6936 *buffer_handle = 0;
6937 delete pbuf;
6938 return BM_CORRUPTED;
6939 }
6940
6941 if ((pheader->max_client_index < 0) || (pheader->max_client_index > MAX_CLIENTS)) {
6942 // unlock before calling cm_msg(). if we are SYSMSG, we wil ldeadlock. K.O.
6943 pbuf_guard.unlock();
6944 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
6945 cm_msg(MERROR, "bm_open_buffer", "Buffer \"%s\" is corrupted, max_client_index %d exceeds MAX_CLIENTS %d",
6947 *buffer_handle = 0;
6948 delete pbuf;
6949 return BM_CORRUPTED;
6950 }
6951
6952 /* check if buffer size is identical */
6953 if (pheader->size != buffer_size) {
6954 cm_msg(MINFO, "bm_open_buffer", "Buffer \"%s\" requested size %d differs from existing size %d",
6955 buffer_name, buffer_size, pheader->size);
6956
6957 buffer_size = pheader->size;
6958
6959 ss_shm_close(buffer_name, p, shm_size, shm_handle, FALSE);
6960
6961 status = ss_shm_open(buffer_name, sizeof(BUFFER_HEADER) + buffer_size, &p, &shm_size, &shm_handle, FALSE);
6962
6963 if (status != SS_SUCCESS) {
6964 *buffer_handle = 0;
6965 pbuf_guard.unlock();
6966 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
6967 delete pbuf;
6968 return BM_NO_SHM;
6969 }
6970
6971 pbuf->buffer_header = (BUFFER_HEADER *) p;
6972 pheader = pbuf->buffer_header;
6973 }
6974 }
6975
6976 /* shared memory is good from here down */
6977
6978 pbuf->attached = true;
6979
6980 pbuf->shm_handle = shm_handle;
6981 pbuf->shm_size = shm_size;
6982 pbuf->callback = FALSE;
6983
6984 bm_cleanup_buffer_locked(pbuf, "bm_open_buffer", ss_millitime());
6985
6987 if (status != BM_SUCCESS) {
6988 cm_msg(MERROR, "bm_open_buffer",
6989 "buffer \'%s\' is corrupted, bm_validate_buffer() status %d, calling bm_reset_buffer()...", buffer_name,
6990 status);
6992 cm_msg(MINFO, "bm_open_buffer", "buffer \'%s\' was reset, all buffered events were lost", buffer_name);
6993 }
6994
6995 /* add our client BUFFER_HEADER */
6996
6997 int iclient = 0;
6998 for (; iclient < MAX_CLIENTS; iclient++)
6999 if (pheader->client[iclient].pid == 0)
7000 break;
7001
7002 if (iclient == MAX_CLIENTS) {
7003 *buffer_handle = 0;
7004 // unlock before calling cm_msg(). if we are SYSMSG, we wil ldeadlock. K.O.
7005 pbuf_guard.unlock();
7006 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
7007 delete pbuf;
7008 cm_msg(MERROR, "bm_open_buffer", "buffer \'%s\' maximum number of clients %d exceeded", buffer_name, MAX_CLIENTS);
7009 return BM_NO_SLOT;
7010 }
7011
7012 /* store slot index in _buffer structure */
7013 pbuf->client_index = iclient;
7014
7015 /*
7016 Save the index of the last client of that buffer so that later only
7017 the clients 0..max_client_index-1 have to be searched through.
7018 */
7019 pheader->num_clients++;
7020 if (iclient + 1 > pheader->max_client_index)
7021 pheader->max_client_index = iclient + 1;
7022
7023 /* setup buffer header and client structure */
7024 BUFFER_CLIENT *pclient = &pheader->client[iclient];
7025
7026 memset(pclient, 0, sizeof(BUFFER_CLIENT));
7027
7028 mstrlcpy(pclient->name, client_name.c_str(), sizeof(pclient->name));
7029
7030 pclient->pid = ss_getpid();
7031
7033
7034 pclient->read_pointer = pheader->write_pointer;
7035 pclient->last_activity = ss_millitime();
7036
7038
7039 pbuf_guard.unlock();
7040
7041 /* shared memory is not locked from here down, do not touch pheader and pbuf->buffer_header! */
7042
7043 pheader = NULL;
7044
7045 /* we are not holding any locks from here down, but other threads cannot see this pbuf yet */
7046
7049
7050 /* add pbuf to buffer list */
7051
7052 gBuffersMutex.lock();
7053
7054 bool added = false;
7055 for (size_t i=0; i<gBuffers.size(); i++) {
7056 if (gBuffers[i] == NULL) {
7057 gBuffers[i] = pbuf;
7058 added = true;
7059 *buffer_handle = i+1;
7060 break;
7061 }
7062 }
7063 if (!added) {
7064 *buffer_handle = gBuffers.size() + 1;
7065 gBuffers.push_back(pbuf);
7066 }
7067
7068 /* from here down we should not touch pbuf without locking it */
7069
7070 pbuf = NULL;
7071
7072 gBuffersMutex.unlock();
7073
7074 /* new buffer is now ready for use */
7075
7076 /* initialize buffer counters */
7077 bm_init_buffer_counters(*buffer_handle);
7078
7079 bm_cleanup("bm_open_buffer", ss_millitime(), FALSE);
7080
7081 if (shm_created)
7082 return BM_CREATED;
7083 }
7084#endif /* LOCAL_ROUTINES */
7085
7086 return BM_SUCCESS;
7087}
static void bm_cleanup_buffer_locked(BUFFER *pbuf, const char *who, DWORD actual_time)
Definition midas.cxx:6084
static DWORD _bm_max_event_size
Definition midas.cxx:5932
static void bm_clear_buffer_statistics(HNDLE hDB, BUFFER *pbuf)
Definition midas.cxx:6426
static void bm_reset_buffer_locked(BUFFER *pbuf)
Definition midas.cxx:6409
INT cm_get_watchdog_params(BOOL *call_watchdog, DWORD *timeout)
Definition midas.cxx:3341
std::string cm_get_client_name()
Definition midas.cxx:2075
static void bm_cleanup(const char *who, DWORD actual_time, BOOL wrong_interval)
Definition midas.cxx:6170
#define BM_NO_SLOT
Definition midas.h:610
#define BM_NO_SHM
Definition midas.h:622
#define BM_CREATED
Definition midas.h:606
#define BM_NO_SEMAPHORE
Definition midas.h:611
#define DB_SUCCESS
Definition midas.h:632
#define SS_SUCCESS
Definition midas.h:664
#define SS_CREATED
Definition midas.h:665
#define SUCCESS
Definition mcstd.h:54
#define MESSAGE_BUFFER_NAME
Definition msystem.h:111
#define MESSAGE_BUFFER_SIZE
Definition msystem.h:110
INT ss_semaphore_create(const char *name, HNDLE *semaphore_handle)
Definition system.cxx:2532
INT ss_getpid(void)
Definition system.cxx:1379
INT ss_shm_open(const char *name, INT size, void **adr, size_t *shm_size, HNDLE *handle, BOOL get_size)
Definition system.cxx:326
midas_thread_t ss_gettid(void)
Definition system.cxx:1591
INT ss_suspend_get_buffer_port(midas_thread_t thread_id, INT *port)
Definition system.cxx:4432
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
Definition odb.cxx:5680
#define RPC_BM_OPEN_BUFFER
Definition mrpc.h:36
INT bm_init_buffer_counters(INT buffer_handle)
Definition midas.cxx:8083
#define DEFAULT_MAX_EVENT_SIZE
Definition midas.h:254
#define NAME_LENGTH
Definition midas.h:272
INT client_index
Definition midas.h:990
int client_count_write_wait[MAX_CLIENTS]
Definition midas.h:1023
DWORD client_time_write_wait[MAX_CLIENTS]
Definition midas.h:1024
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_peek_buffer_locked()

static int bm_peek_buffer_locked ( BUFFER pbuf,
BUFFER_HEADER pheader,
BUFFER_CLIENT pc,
EVENT_HEADER **  ppevent,
int *  pevent_size,
int *  ptotal_size 
)
static

Definition at line 8911 of file midas.cxx.

8912{
8913 if (pc->read_pointer == pheader->write_pointer) {
8914 /* no more events buffered for this client */
8915 if (!pc->read_wait) {
8916 //printf("bm_peek_buffer_locked: buffer [%s] client [%s], set read_wait!\n", pheader->name, pc->name);
8917 pc->read_wait = TRUE;
8918 }
8919 return BM_ASYNC_RETURN;
8920 }
8921
8922 if (pc->read_wait) {
8923 //printf("bm_peek_buffer_locked: buffer [%s] client [%s], clear read_wait!\n", pheader->name, pc->name);
8924 pc->read_wait = FALSE;
8925 }
8926
8927 if ((pc->read_pointer < 0) || (pc->read_pointer >= pheader->size)) {
8928 cm_msg(MERROR, "bm_peek_buffer_locked", "event buffer \"%s\" is corrupted: client \"%s\" read pointer %d is invalid. buffer read pointer %d, write pointer %d, size %d", pheader->name, pc->name, pc->read_pointer, pheader->read_pointer, pheader->write_pointer, pheader->size);
8929 return BM_CORRUPTED;
8930 }
8931
8932 char *pdata = (char *) (pheader + 1);
8933
8934 EVENT_HEADER *pevent = (EVENT_HEADER *) (pdata + pc->read_pointer);
8935 int event_size = pevent->data_size + sizeof(EVENT_HEADER);
8936 int total_size = ALIGN8(event_size);
8937
8938 if ((total_size <= 0) || (total_size > pheader->size)) {
8939 cm_msg(MERROR, "bm_peek_buffer_locked", "event buffer \"%s\" is corrupted: client \"%s\" read pointer %d points to invalid event: data_size %d, event_size %d, total_size %d. buffer size: %d, read_pointer: %d, write_pointer: %d", pheader->name, pc->name, pc->read_pointer, pevent->data_size, event_size, total_size, pheader->size, pheader->read_pointer, pheader->write_pointer);
8940 return BM_CORRUPTED;
8941 }
8942
8943 assert(total_size > 0);
8944 assert(total_size <= pheader->size);
8945
8946 if (ppevent)
8947 *ppevent = pevent;
8948 if (pevent_size)
8949 *pevent_size = event_size;
8950 if (ptotal_size)
8951 *ptotal_size = total_size;
8952
8953 return BM_SUCCESS;
8954}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_peek_read_cache_locked()

static BOOL bm_peek_read_cache_locked ( BUFFER pbuf,
EVENT_HEADER **  ppevent,
int *  pevent_size,
int *  ptotal_size 
)
static

Definition at line 8885 of file midas.cxx.

8886{
8887 if (pbuf->read_cache_rp == pbuf->read_cache_wp)
8888 return FALSE;
8889
8890 EVENT_HEADER *pevent = (EVENT_HEADER *) (pbuf->read_cache + pbuf->read_cache_rp);
8891 int event_size = pevent->data_size + sizeof(EVENT_HEADER);
8892 int total_size = ALIGN8(event_size);
8893
8894 if (ppevent)
8895 *ppevent = pevent;
8896 if (pevent_size)
8897 *pevent_size = event_size;
8898 if (ptotal_size)
8899 *ptotal_size = total_size;
8900
8901 return TRUE;
8902}
Here is the caller graph for this function:

◆ bm_poll_event()

INT bm_poll_event ( void  )

Definition at line 11274 of file midas.cxx.

11288{
11289 BOOL dispatched_something = FALSE;
11290
11291 //printf("bm_poll_event!\n");
11292
11293 DWORD start_time = ss_millitime();
11294
11295 std::vector<char> vec;
11296
11297 /* loop over all requests */
11298 _request_list_mutex.lock();
11299 bool locked = true;
11300 size_t n = _request_list.size();
11301 for (size_t i = 0; i < n; i++) {
11302 if (!locked) {
11303 _request_list_mutex.lock();
11304 locked = true;
11305 }
11306 /* continue if no dispatcher set (manual bm_receive_event) */
11307 if (_request_list[i].dispatcher == NULL)
11308 continue;
11309
11310 int buffer_handle = _request_list[i].buffer_handle;
11311
11312 /* must release the lock on the request list: user provided r.dispatcher() can add or remove event requests, and we will deadlock. K.O. */
11313 _request_list_mutex.unlock();
11314 locked = false;
11315
11316 do {
11317 /* receive event */
11318 int status = bm_receive_event_vec(buffer_handle, &vec, BM_NO_WAIT);
11319
11320 //printf("bm_poll_event: request_id %d, buffer_handle %d, bm_receive_event(BM_NO_WAIT) status %d, vec size %d, capacity %d\n", request_id, buffer_handle, status, (int)vec.size(), (int)vec.capacity());
11321
11322 /* call user function if successful */
11323 if (status == BM_SUCCESS) {
11324 bm_dispatch_event(buffer_handle, (EVENT_HEADER*)vec.data());
11325 dispatched_something = TRUE;
11326 }
11327
11328 /* break if no more events */
11329 if (status == BM_ASYNC_RETURN)
11330 break;
11331
11332 /* break if corrupted event buffer */
11333 if (status == BM_TRUNCATED) {
11334 cm_msg(MERROR, "bm_poll_event", "received event was truncated, buffer size %d is too small, see messages and increase /Experiment/MAX_EVENT_SIZE in ODB", (int)vec.size());
11335 }
11336
11337 /* break if corrupted event buffer */
11338 if (status == BM_CORRUPTED)
11339 return SS_ABORT;
11340
11341 /* break if server died */
11342 if (status == RPC_NET_ERROR) {
11343 return SS_ABORT;
11344 }
11345
11346 /* stop after one second */
11347 if (ss_millitime() - start_time > 1000) {
11348 break;
11349 }
11350
11351 } while (TRUE);
11352 }
11353
11354 if (locked)
11355 _request_list_mutex.unlock();
11356
11357 if (dispatched_something)
11358 return BM_SUCCESS;
11359 else
11360 return BM_ASYNC_RETURN;
11361}
INT bm_receive_event_vec(INT buffer_handle, std::vector< char > *pvec, int timeout_msec)
Definition midas.cxx:10957
static void bm_dispatch_event(int buffer_handle, EVENT_HEADER *pevent)
Definition midas.cxx:8843
#define BM_TRUNCATED
Definition midas.h:614
#define RPC_NET_ERROR
Definition midas.h:702
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_push_buffer()

static INT bm_push_buffer ( BUFFER pbuf,
int  buffer_handle 
)
static

Check a buffer if an event is available and call the dispatch function if found.

Parameters
buffer_nameName of buffer
Returns
BM_SUCCESS, BM_INVALID_HANDLE, BM_TRUNCATED, BM_ASYNC_RETURN, RPC_NET_ERROR

Definition at line 11050 of file midas.cxx.

11050 {
11051 //printf("bm_push_buffer: buffer [%s], handle %d, callback %d\n", pbuf->buffer_header->name, buffer_handle, pbuf->callback);
11052
11053 /* return immediately if no callback routine is defined */
11054 if (!pbuf->callback)
11055 return BM_SUCCESS;
11056
11057 return bm_read_buffer(pbuf, buffer_handle, NULL, NULL, NULL, NULL, BM_NO_WAIT, 0, TRUE);
11058}
static INT bm_read_buffer(BUFFER *pbuf, INT buffer_handle, void **bufptr, void *buf, INT *buf_size, std::vector< char > *vecptr, int timeout_msec, int convert_flags, BOOL dispatch)
Definition midas.cxx:10299
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_read_buffer()

static INT bm_read_buffer ( BUFFER pbuf,
INT  buffer_handle,
void **  bufptr,
void *  buf,
INT buf_size,
std::vector< char > *  vecptr,
int  timeout_msec,
int  convert_flags,
BOOL  dispatch 
)
static

Definition at line 10299 of file midas.cxx.

10299 {
10301
10302 int max_size = 0;
10303 if (buf_size) {
10304 max_size = *buf_size;
10305 *buf_size = 0;
10306 }
10307
10308 //printf("bm_read_buffer: [%s] timeout %d, conv %d, ptr %p, buf %p, disp %d\n", pbuf->buffer_name, timeout_msec, convert_flags, bufptr, buf, dispatch);
10309
10310 bm_lock_buffer_guard pbuf_guard(pbuf, true); // buffer is not locked
10311
10312 // NB: locking order is: 1st read cache lock, 2nd buffer lock, unlock in reverse order
10313
10314 /* look if there is anything in the cache */
10315 if (pbuf->read_cache_size > 0) {
10316
10318
10319 if (status != BM_SUCCESS)
10320 return status;
10321
10322 if (pbuf->read_cache_wp == 0) {
10323
10324 // lock buffer for the first time
10325
10326 if (!pbuf_guard.relock()) {
10327 pbuf->read_cache_mutex.unlock();
10328 return pbuf_guard.get_status();
10329 }
10330
10331 status = bm_fill_read_cache_locked(pbuf_guard, timeout_msec);
10332 if (status != BM_SUCCESS) {
10333 // unlock in correct order
10334 if (pbuf_guard.is_locked()) {
10335 // check if bm_wait_for_more_events() failed to relock the buffer
10336 pbuf_guard.unlock();
10337 }
10338 pbuf->read_cache_mutex.unlock();
10339 return status;
10340 }
10341
10342 // buffer remains locked here
10343 }
10344 EVENT_HEADER *pevent;
10345 int event_size;
10346 int total_size;
10347 if (bm_peek_read_cache_locked(pbuf, &pevent, &event_size, &total_size)) {
10348 if (pbuf_guard.is_locked()) {
10349 // do not need to keep the event buffer locked
10350 // when reading from the read cache
10351 pbuf_guard.unlock();
10352 }
10353 //printf("bm_read_buffer: [%s] async %d, conv %d, ptr %p, buf %p, disp %d, total_size %d, read from cache %d %d %d\n", pbuf->buffer_name, async_flag, convert_flags, bufptr, buf, dispatch, total_size, pbuf->read_cache_size, pbuf->read_cache_rp, pbuf->read_cache_wp);
10355 if (buf) {
10356 if (event_size > max_size) {
10357 cm_msg(MERROR, "bm_read_buffer", "buffer size %d is smaller than event size %d, event truncated. buffer \"%s\"", max_size, event_size, pbuf->buffer_name);
10358 event_size = max_size;
10360 }
10361
10362 memcpy(buf, pevent, event_size);
10363
10364 if (buf_size) {
10365 *buf_size = event_size;
10366 }
10367 if (convert_flags) {
10368 bm_convert_event_header((EVENT_HEADER *) buf, convert_flags);
10369 }
10370 } else if (bufptr) {
10371 *bufptr = malloc(event_size);
10372 memcpy(*bufptr, pevent, event_size);
10374 } else if (vecptr) {
10375 vecptr->resize(0);
10376 char* cptr = (char*)pevent;
10377 vecptr->assign(cptr, cptr+event_size);
10378 }
10379 bm_incr_read_cache_locked(pbuf, total_size);
10380 pbuf->read_cache_mutex.unlock();
10381 if (dispatch) {
10382 // FIXME need to protect currently dispatched event against
10383 // another thread overwriting it by refilling the read cache
10384 bm_dispatch_event(buffer_handle, pevent);
10385 return BM_MORE_EVENTS;
10386 }
10387 // buffer is unlocked here
10388 return status;
10389 }
10390 pbuf->read_cache_mutex.unlock();
10391 }
10392
10393 /* we come here if the read cache is disabled */
10394 /* we come here if the next event is too big to fit into the read cache */
10395
10396 if (!pbuf_guard.is_locked()) {
10397 if (!pbuf_guard.relock())
10398 return pbuf_guard.get_status();
10399 }
10400
10401 EVENT_HEADER *event_buffer = NULL;
10402
10403 BUFFER_HEADER *pheader = pbuf->buffer_header;
10404
10405 BUFFER_CLIENT *pc = bm_get_my_client_locked(pbuf_guard);
10406
10407 while (1) {
10408 /* loop over events in the event buffer */
10409
10410 status = bm_wait_for_more_events_locked(pbuf_guard, pc, timeout_msec, FALSE);
10411
10412 if (status != BM_SUCCESS) {
10413 // implicit unlock
10414 return status;
10415 }
10416
10417 /* check if event at current read pointer matches a request */
10418
10419 EVENT_HEADER *pevent;
10420 int event_size;
10421 int total_size;
10422
10423 status = bm_peek_buffer_locked(pbuf, pheader, pc, &pevent, &event_size, &total_size);
10424 if (status == BM_CORRUPTED) {
10425 // implicit unlock
10426 return status;
10427 } else if (status != BM_SUCCESS) {
10428 /* event buffer is empty */
10429 break;
10430 }
10431
10432 BOOL is_requested = bm_check_requests(pc, pevent);
10433
10434 if (is_requested) {
10435 //printf("bm_read_buffer: [%s] async %d, conv %d, ptr %p, buf %p, disp %d, total_size %d, read from buffer, cache %d %d %d\n", pheader->name, async_flag, convert_flags, bufptr, buf, dispatch, total_size, pbuf->read_cache_size, pbuf->read_cache_rp, pbuf->read_cache_wp);
10436
10438
10439 if (buf) {
10440 if (event_size > max_size) {
10441 cm_msg(MERROR, "bm_read_buffer",
10442 "buffer size %d is smaller than event size %d, event truncated. buffer \"%s\"", max_size,
10443 event_size, pheader->name);
10444 event_size = max_size;
10446 }
10447
10448 bm_read_from_buffer_locked(pheader, pc->read_pointer, (char *) buf, event_size);
10449
10450 if (buf_size) {
10451 *buf_size = event_size;
10452 }
10453
10454 if (convert_flags) {
10455 bm_convert_event_header((EVENT_HEADER *) buf, convert_flags);
10456 }
10457
10458 pbuf->count_read++;
10459 pbuf->bytes_read += event_size;
10460 } else if (dispatch || bufptr) {
10461 assert(event_buffer == NULL); // make sure we only come here once
10462 event_buffer = (EVENT_HEADER *) malloc(event_size);
10464 pbuf->count_read++;
10465 pbuf->bytes_read += event_size;
10466 } else if (vecptr) {
10467 bm_read_from_buffer_locked(pheader, pc->read_pointer, vecptr, event_size);
10468 pbuf->count_read++;
10469 pbuf->bytes_read += event_size;
10470 }
10471
10472 int new_read_pointer = bm_incr_rp_no_check(pheader, pc->read_pointer, total_size);
10473 pc->read_pointer = new_read_pointer;
10474
10475 pheader->num_out_events++;
10476 /* exit loop over events */
10477 break;
10478 }
10479
10480 int new_read_pointer = bm_incr_rp_no_check(pheader, pc->read_pointer, total_size);
10481 pc->read_pointer = new_read_pointer;
10482 pheader->num_out_events++;
10483 }
10484
10485 /*
10486 If read pointer has been changed, it may have freed up some space
10487 for waiting producers. So check if free space is now more than 50%
10488 of the buffer size and wake waiting producers.
10489 */
10490
10491 bm_wakeup_producers_locked(pheader, pc);
10492
10493 pbuf_guard.unlock();
10494
10495 if (dispatch && event_buffer) {
10496 bm_dispatch_event(buffer_handle, event_buffer);
10497 free(event_buffer);
10498 event_buffer = NULL;
10499 return BM_MORE_EVENTS;
10500 }
10501
10502 if (bufptr && event_buffer) {
10503 *bufptr = event_buffer;
10504 event_buffer = NULL;
10506 }
10507
10508 if (event_buffer) {
10509 free(event_buffer);
10510 event_buffer = NULL;
10511 }
10512
10513 return status;
10514}
static void bm_convert_event_header(EVENT_HEADER *pevent, int convert_flags)
Definition midas.cxx:9089
static int bm_fill_read_cache_locked(bm_lock_buffer_guard &pbuf_guard, int timeout_msec)
Definition midas.cxx:9012
static BOOL bm_peek_read_cache_locked(BUFFER *pbuf, EVENT_HEADER **ppevent, int *pevent_size, int *ptotal_size)
Definition midas.cxx:8885
static void bm_incr_read_cache_locked(BUFFER *pbuf, int total_size)
Definition midas.cxx:8875
void * event_buffer
Definition mfe.cxx:65
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_read_from_buffer_locked() [1/2]

static void bm_read_from_buffer_locked ( const BUFFER_HEADER pheader,
int  rp,
char *  buf,
int  event_size 
)
static

Definition at line 8956 of file midas.cxx.

8957{
8958 const char *pdata = (const char *) (pheader + 1);
8959
8960 if (rp + event_size <= pheader->size) {
8961 /* copy event to cache */
8962 memcpy(buf, pdata + rp, event_size);
8963 } else {
8964 /* event is splitted */
8965 int size = pheader->size - rp;
8966 memcpy(buf, pdata + rp, size);
8967 memcpy(buf + size, pdata, event_size - size);
8968 }
8969}
Here is the caller graph for this function:

◆ bm_read_from_buffer_locked() [2/2]

static void bm_read_from_buffer_locked ( const BUFFER_HEADER pheader,
int  rp,
std::vector< char > *  vecptr,
int  event_size 
)
static

Definition at line 8971 of file midas.cxx.

8972{
8973 const char *pdata = (const char *) (pheader + 1);
8974
8975 if (rp + event_size <= pheader->size) {
8976 /* copy event to cache */
8977 vecptr->assign(pdata + rp, pdata + rp + event_size);
8978 } else {
8979 /* event is splitted */
8980 int size = pheader->size - rp;
8981 vecptr->assign(pdata + rp, pdata + rp + size);
8982 vecptr->insert(vecptr->end(), pdata, pdata + event_size - size);
8983 }
8984}

◆ bm_receive_event()

INT bm_receive_event ( INT  buffer_handle,
void *  destination,
INT buf_size,
int  timeout_msec 
)

Receives events directly. This function is an alternative way to receive events without a main loop.

It can be used in analysis systems which actively receive events, rather than using callbacks. A analysis package could for example contain its own command line interface. A command like "receive 1000 events" could make it necessary to call bm_receive_event() 1000 times in a row to receive these events and then return back to the command line prompt. The according bm_request_event() call contains NULL as the callback routine to indicate that bm_receive_event() is called to receive events.

#include <stdio.h>
#include "midas.h"
{
printf("Received event #%d\r",
pheader->serial_number);
}
{
INT status, request_id;
HNDLE hbuf;
char event_buffer[1000];
status = cm_connect_experiment("", "Sample",
"Simple Analyzer", NULL);
return 1;
bm_request_event(hbuf, 1, TRIGGER_ALL, GET_ALL, request_id, NULL);
do
{
size = sizeof(event_buffer);
<...do something else...>
} while (status != RPC_SHUTDOWN &&
return 0;
}
INT bm_receive_event(INT buffer_handle, void *destination, INT *buf_size, int timeout_msec)
Definition midas.cxx:10798
Parameters
buffer_handlebuffer handle
destinationdestination address where event is written to
buf_sizesize of destination buffer on input, size of event plus header on return.
timeout_msecWait so many millisecond for new data. Special values: BM_WAIT: wait forever, BM_NO_WAIT: do not wait, return BM_ASYNC_RETURN if no data is immediately available
Returns
BM_SUCCESS, BM_INVALID_HANDLE
BM_TRUNCATED The event is larger than the destination buffer and was therefore truncated
BM_ASYNC_RETURN No event available

Definition at line 10798 of file midas.cxx.

10798 {
10799 //printf("bm_receive_event: handle %d, async %d\n", buffer_handle, async_flag);
10800 if (rpc_is_remote()) {
10801 return bm_receive_event_rpc(buffer_handle, destination, buf_size, NULL, NULL, timeout_msec);
10802 }
10803#ifdef LOCAL_ROUTINES
10804 {
10806
10807 BUFFER *pbuf = bm_get_buffer("bm_receive_event", buffer_handle, &status);
10808
10809 if (!pbuf)
10810 return status;
10811
10812 int convert_flags = rpc_get_convert_flags();
10813
10814 status = bm_read_buffer(pbuf, buffer_handle, NULL, destination, buf_size, NULL, timeout_msec, convert_flags, FALSE);
10815 //printf("bm_receive_event: handle %d, async %d, status %d, size %d\n", buffer_handle, async_flag, status, *buf_size);
10816 return status;
10817 }
10818#else /* LOCAL_ROUTINES */
10819
10820 return BM_SUCCESS;
10821#endif
10822}
static INT bm_receive_event_rpc(INT buffer_handle, void *buf, int *buf_size, EVENT_HEADER **ppevent, std::vector< char > *pvec, int timeout_msec)
Definition midas.cxx:10518
INT rpc_get_convert_flags(void)
Definition midas.cxx:13170
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_receive_event_alloc()

INT bm_receive_event_alloc ( INT  buffer_handle,
EVENT_HEADER **  ppevent,
int  timeout_msec 
)

Receives events directly. This function is an alternative way to receive events without a main loop.

It can be used in analysis systems which actively receive events, rather than using callbacks. A analysis package could for example contain its own command line interface. A command like "receive 1000 events" could make it necessary to call bm_receive_event() 1000 times in a row to receive these events and then return back to the command line prompt. The according bm_request_event() call contains NULL as the callback routine to indicate that bm_receive_event() is called to receive events.

#include <stdio.h>
#include "midas.h"
{
printf("Received event #%d\r",
pheader->serial_number);
}
{
INT status, request_id;
HNDLE hbuf;
char event_buffer[1000];
status = cm_connect_experiment("", "Sample",
"Simple Analyzer", NULL);
return 1;
bm_request_event(hbuf, 1, TRIGGER_ALL, GET_ALL, request_id, NULL);
do
{
size = sizeof(event_buffer);
<...do something else...>
} while (status != RPC_SHUTDOWN &&
return 0;
}
Parameters
buffer_handlebuffer handle
ppeventpointer to the received event pointer, event pointer should be free()ed to avoid memory leak
timeout_msecWait so many millisecond for new data. Special values: BM_WAIT: wait forever, BM_NO_WAIT: do not wait, return BM_ASYNC_RETURN if no data is immediately available
Returns
BM_SUCCESS, BM_INVALID_HANDLE
BM_ASYNC_RETURN No event available

Definition at line 10879 of file midas.cxx.

10879 {
10880 if (rpc_is_remote()) {
10881 return bm_receive_event_rpc(buffer_handle, NULL, NULL, ppevent, NULL, timeout_msec);
10882 }
10883#ifdef LOCAL_ROUTINES
10884 {
10886
10887 BUFFER *pbuf = bm_get_buffer("bm_receive_event_alloc", buffer_handle, &status);
10888
10889 if (!pbuf)
10890 return status;
10891
10892 int convert_flags = rpc_get_convert_flags();
10893
10894 return bm_read_buffer(pbuf, buffer_handle, (void **) ppevent, NULL, NULL, NULL, timeout_msec, convert_flags, FALSE);
10895 }
10896#else /* LOCAL_ROUTINES */
10897
10898 return BM_SUCCESS;
10899#endif
10900}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_receive_event_rpc()

static INT bm_receive_event_rpc ( INT  buffer_handle,
void *  buf,
int *  buf_size,
EVENT_HEADER **  ppevent,
std::vector< char > *  pvec,
int  timeout_msec 
)
static

Definition at line 10518 of file midas.cxx.

10519{
10520 //printf("bm_receive_event_rpc: handle %d, buf %p, pevent %p, pvec %p, timeout %d, max_event_size %d\n", buffer_handle, buf, ppevent, pvec, timeout_msec, _bm_max_event_size);
10521
10522 assert(_bm_max_event_size > sizeof(EVENT_HEADER));
10523
10524 void *xbuf = NULL;
10525 int xbuf_size = 0;
10526
10527 if (buf) {
10528 xbuf = buf;
10529 xbuf_size = *buf_size;
10530 } else if (ppevent) {
10531 *ppevent = (EVENT_HEADER*)malloc(_bm_max_event_size);
10532 xbuf_size = _bm_max_event_size;
10533 } else if (pvec) {
10534 pvec->resize(_bm_max_event_size);
10535 xbuf = pvec->data();
10536 xbuf_size = pvec->size();
10537 } else {
10538 assert(!"incorrect call to bm_receivent_event_rpc()");
10539 }
10540
10541 int status;
10542 DWORD time_start = ss_millitime();
10543 DWORD time_end = time_start + timeout_msec;
10544
10545 int xtimeout_msec = timeout_msec;
10546
10547 int zbuf_size = xbuf_size;
10548
10549 while (1) {
10550 if (timeout_msec == BM_WAIT) {
10551 xtimeout_msec = 1000;
10552 } else if (timeout_msec == BM_NO_WAIT) {
10553 xtimeout_msec = BM_NO_WAIT;
10554 } else {
10555 if (xtimeout_msec > 1000) {
10556 xtimeout_msec = 1000;
10557 }
10558 }
10559
10560 zbuf_size = xbuf_size;
10561
10562 status = rpc_call(RPC_BM_RECEIVE_EVENT, buffer_handle, xbuf, &zbuf_size, xtimeout_msec);
10563
10564 //printf("bm_receive_event_rpc: handle %d, timeout %d, status %d, size %d in, %d out, via RPC_BM_RECEIVE_EVENT\n", buffer_handle, xtimeout_msec, status, xbuf_size, zbuf_size);
10565
10566 if (status == BM_ASYNC_RETURN) {
10567 if (timeout_msec == BM_WAIT) {
10568 // BM_WAIT means wait forever
10569 continue;
10570 } else if (timeout_msec == BM_NO_WAIT) {
10571 // BM_NO_WAIT means do not wait
10572 break;
10573 } else {
10574 DWORD now = ss_millitime();
10575 if (now >= time_end) {
10576 // timeout, return BM_ASYNC_RETURN
10577 break;
10578 }
10579
10580 DWORD remain = time_end - now;
10581
10582 if (remain < (DWORD)xtimeout_msec) {
10583 xtimeout_msec = remain;
10584 }
10585
10586 // keep asking for event...
10587 continue;
10588 }
10589 } else if (status == BM_SUCCESS) {
10590 // success, return BM_SUCCESS
10591 break;
10592 }
10593
10594 // RPC error
10595
10596 if (buf) {
10597 *buf_size = 0;
10598 } else if (ppevent) {
10599 free(*ppevent);
10600 *ppevent = NULL;
10601 } else if (pvec) {
10602 pvec->resize(0);
10603 } else {
10604 assert(!"incorrect call to bm_receivent_event_rpc()");
10605 }
10606
10607 return status;
10608 }
10609
10610 // status is BM_SUCCESS or BM_ASYNC_RETURN
10611
10612 if (buf) {
10613 *buf_size = zbuf_size;
10614 } else if (ppevent) {
10615 // nothing to do
10616 // ppevent = realloc(ppevent, xbuf_size); // shrink memory allocation
10617 } else if (pvec) {
10618 pvec->resize(zbuf_size);
10619 } else {
10620 assert(!"incorrect call to bm_receivent_event_rpc()");
10621 }
10622
10623 return status;
10624}
#define RPC_BM_RECEIVE_EVENT
Definition mrpc.h:47
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_receive_event_rpc_cxx()

static INT bm_receive_event_rpc_cxx ( INT  buffer_handle,
void *  buf,
int *  buf_size,
EVENT_HEADER **  ppevent,
std::vector< char > *  pvec,
int  timeout_msec 
)
static

Definition at line 10626 of file midas.cxx.

10627{
10628 //printf("bm_receive_event_rpc_cxx: handle %d, buf %p, pevent %p, pvec %p, timeout %d, max_event_size %d\n", buffer_handle, buf, ppevent, pvec, timeout_msec, _bm_max_event_size);
10629
10630 std::vector<char> *pv;
10631
10632 if (pvec == NULL)
10633 pv = new std::vector<char>;
10634 else
10635 pv = pvec;
10636
10637 pv->clear();
10638
10639 int status;
10640 DWORD time_start = ss_millitime();
10641 DWORD time_end = time_start + timeout_msec;
10642
10643 int xtimeout_msec = timeout_msec;
10644
10645 while (1) {
10646 if (timeout_msec == BM_WAIT) {
10647 xtimeout_msec = 1000;
10648 } else if (timeout_msec == BM_NO_WAIT) {
10649 xtimeout_msec = BM_NO_WAIT;
10650 } else {
10651 if (xtimeout_msec > 1000) {
10652 xtimeout_msec = 1000;
10653 }
10654 }
10655
10656 status = rpc_call(RPC_BM_RECEIVE_EVENT_CXX, buffer_handle, pv, xtimeout_msec);
10657
10658 printf("bm_receive_event_rpc_cxx: handle %d, timeout %d, status %d, size %zu, via RPC_BM_RECEIVE_EVENT_CXX\n", buffer_handle, xtimeout_msec, status, pv->size());
10659
10660 if (status == BM_ASYNC_RETURN) {
10661 if (timeout_msec == BM_WAIT) {
10662 // BM_WAIT means wait forever
10663 continue;
10664 } else if (timeout_msec == BM_NO_WAIT) {
10665 // BM_NO_WAIT means do not wait
10666 break;
10667 } else {
10668 DWORD now = ss_millitime();
10669 if (now >= time_end) {
10670 // timeout, return BM_ASYNC_RETURN
10671 break;
10672 }
10673
10674 DWORD remain = time_end - now;
10675
10676 if (remain < (DWORD)xtimeout_msec) {
10677 xtimeout_msec = remain;
10678 }
10679
10680 // keep asking for event...
10681 continue;
10682 }
10683 } else if (status == BM_SUCCESS) {
10684 // success, return BM_SUCCESS
10685 break;
10686 }
10687
10688 // RPC error
10689
10690 if (buf) {
10691 *buf_size = 0;
10692 } else if (ppevent) {
10693 free(*ppevent);
10694 *ppevent = NULL;
10695 } else if (pvec) {
10696 pvec->clear();
10697 } else {
10698 assert(!"incorrect call to bm_receivent_event_rpc_cxx()");
10699 }
10700
10701 if (pvec == NULL)
10702 delete pv;
10703
10704 return status;
10705 }
10706
10707 // status is BM_SUCCESS or BM_ASYNC_RETURN
10708
10709 if (buf) {
10710 if (pv->size() > (size_t)*buf_size) {
10712 memcpy(buf, pv->data(), *buf_size);
10713 } else {
10714 *buf_size = pv->size();
10715 memcpy(buf, pv->data(), *buf_size);
10716 }
10717 } else if (ppevent) {
10718 if (*ppevent == NULL) {
10719 *ppevent = (EVENT_HEADER*)malloc(pv->size());
10720 assert(*ppevent != NULL);
10721 memcpy(*ppevent, pv->data(), pv->size());
10722 } else {
10723 *ppevent = (EVENT_HEADER*)realloc(*ppevent, pv->size()); // shrink memory allocation
10724 assert(*ppevent != NULL);
10725 memcpy(*ppevent, pv->data(), pv->size());
10726 }
10727 } else if (pvec) {
10728 // nothing to do
10729 } else {
10730 assert(!"incorrect call to bm_receivent_event_rpc()");
10731 }
10732
10733 if (!pvec)
10734 delete pv;
10735
10736 return status;
10737}
#define RPC_BM_RECEIVE_EVENT_CXX
Definition mrpc.h:51
Here is the call graph for this function:

◆ bm_receive_event_vec()

INT bm_receive_event_vec ( INT  buffer_handle,
std::vector< char > *  pvec,
int  timeout_msec 
)

Receives events directly. This function is an alternative way to receive events without a main loop.

It can be used in analysis systems which actively receive events, rather than using callbacks. A analysis package could for example contain its own command line interface. A command like "receive 1000 events" could make it necessary to call bm_receive_event() 1000 times in a row to receive these events and then return back to the command line prompt. The according bm_request_event() call contains NULL as the callback routine to indicate that bm_receive_event() is called to receive events.

#include <stdio.h>
#include "midas.h"
{
printf("Received event #%d\r",
pheader->serial_number);
}
{
INT status, request_id;
HNDLE hbuf;
char event_buffer[1000];
status = cm_connect_experiment("", "Sample",
"Simple Analyzer", NULL);
return 1;
bm_request_event(hbuf, 1, TRIGGER_ALL, GET_ALL, request_id, NULL);
do
{
size = sizeof(event_buffer);
<...do something else...>
} while (status != RPC_SHUTDOWN &&
return 0;
}
Parameters
buffer_handlebuffer handle
ppeventpointer to the received event pointer, event pointer should be free()ed to avoid memory leak
timeout_msecWait so many millisecond for new data. Special values: BM_WAIT: wait forever, BM_NO_WAIT: do not wait, return BM_ASYNC_RETURN if no data is immediately available
Returns
BM_SUCCESS, BM_INVALID_HANDLE
BM_ASYNC_RETURN No event available

Definition at line 10957 of file midas.cxx.

10957 {
10958 if (rpc_is_remote()) {
10959 return bm_receive_event_rpc(buffer_handle, NULL, NULL, NULL, pvec, timeout_msec);
10960 }
10961#ifdef LOCAL_ROUTINES
10962 {
10964
10965 BUFFER *pbuf = bm_get_buffer("bm_receive_event_vec", buffer_handle, &status);
10966
10967 if (!pbuf)
10968 return status;
10969
10970 int convert_flags = rpc_get_convert_flags();
10971
10972 return bm_read_buffer(pbuf, buffer_handle, NULL, NULL, NULL, pvec, timeout_msec, convert_flags, FALSE);
10973 }
10974#else /* LOCAL_ROUTINES */
10975 return BM_SUCCESS;
10976#endif
10977}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_remove_client_locked()

void bm_remove_client_locked ( BUFFER_HEADER pheader,
int  j 
)

Called to forcibly disconnect given client from a data buffer

Definition at line 6053 of file midas.cxx.

6053 {
6054 int k, nc;
6055 BUFFER_CLIENT *pbctmp;
6056
6057 /* clear entry from client structure in buffer header */
6058 memset(&(pheader->client[j]), 0, sizeof(BUFFER_CLIENT));
6059
6060 /* calculate new max_client_index entry */
6061 for (k = MAX_CLIENTS - 1; k >= 0; k--)
6062 if (pheader->client[k].pid != 0)
6063 break;
6064 pheader->max_client_index = k + 1;
6065
6066 /* count new number of clients */
6067 for (k = MAX_CLIENTS - 1, nc = 0; k >= 0; k--)
6068 if (pheader->client[k].pid != 0)
6069 nc++;
6070 pheader->num_clients = nc;
6071
6072 /* check if anyone is waiting and wake him up */
6073 pbctmp = pheader->client;
6074
6075 for (k = 0; k < pheader->max_client_index; k++, pbctmp++)
6076 if (pbctmp->pid && (pbctmp->write_wait || pbctmp->read_wait))
6077 ss_resume(pbctmp->port, "B ");
6078}
INT k
Definition odbhist.cxx:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_remove_event_request()

INT bm_remove_event_request ( INT  buffer_handle,
INT  request_id 
)

Delete a previously placed request for a specific event type in the client structure of the buffer refereced by buffer_handle.

Parameters
buffer_handleHandle to the buffer where the re- quest should be placed in
request_idRequest id returned by bm_request_event
Returns
BM_SUCCESS, BM_INVALID_HANDLE, BM_NOT_FOUND, RPC_NET_ERROR

Definition at line 8538 of file midas.cxx.

8538 {
8539 if (rpc_is_remote())
8540 return rpc_call(RPC_BM_REMOVE_EVENT_REQUEST, buffer_handle, request_id);
8541
8542#ifdef LOCAL_ROUTINES
8543 {
8544 int status = 0;
8545
8546 BUFFER *pbuf = bm_get_buffer("bm_remove_event_request", buffer_handle, &status);
8547
8548 if (!pbuf)
8549 return status;
8550
8551 /* lock buffer */
8552 bm_lock_buffer_guard pbuf_guard(pbuf);
8553
8554 if (!pbuf_guard.is_locked())
8555 return pbuf_guard.get_status();
8556
8557 INT i, deleted;
8558
8559 /* get a pointer to the proper client structure */
8560 BUFFER_CLIENT *pclient = bm_get_my_client_locked(pbuf_guard);
8561
8562 /* check all requests and set to zero if matching */
8563 for (i = 0, deleted = 0; i < pclient->max_request_index; i++)
8564 if (pclient->event_request[i].valid && pclient->event_request[i].id == request_id) {
8565 memset(&pclient->event_request[i], 0, sizeof(EVENT_REQUEST));
8566 deleted++;
8567 }
8568
8569 /* calculate new max_request_index entry */
8570 for (i = MAX_EVENT_REQUESTS - 1; i >= 0; i--)
8571 if (pclient->event_request[i].valid)
8572 break;
8573
8574 pclient->max_request_index = i + 1;
8575
8576 /* calculate new all_flag */
8577 pclient->all_flag = FALSE;
8578
8579 for (i = 0; i < pclient->max_request_index; i++)
8580 if (pclient->event_request[i].valid && (pclient->event_request[i].sampling_type & GET_ALL)) {
8581 pclient->all_flag = TRUE;
8582 break;
8583 }
8584
8585 pbuf->get_all_flag = pclient->all_flag;
8586
8587 if (!deleted)
8588 return BM_NOT_FOUND;
8589 }
8590#endif /* LOCAL_ROUTINES */
8591
8592 return BM_SUCCESS;
8593}
#define RPC_BM_REMOVE_EVENT_REQUEST
Definition mrpc.h:44
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_request_event()

INT bm_request_event ( HNDLE  buffer_handle,
short int  event_id,
short int  trigger_mask,
INT  sampling_type,
HNDLE request_id,
EVENT_HANDLER func 
)

dox Place an event request based on certain characteristics. Multiple event requests can be placed for each buffer, which are later identified by their request ID. They can contain different callback routines. Example see bm_open_buffer() and bm_receive_event()

Parameters
buffer_handlebuffer handle obtained via bm_open_buffer()
event_idevent ID for requested events. Use EVENTID_ALL to receive events with any ID.
trigger_masktrigger mask for requested events. The requested events must have at least one bit in its trigger mask common with the requested trigger mask. Use TRIGGER_ALL to receive events with any trigger mask.
sampling_typespecifies how many events to receive. A value of GET_ALL receives all events which match the specified event ID and trigger mask. If the events are consumed slower than produced, the producer is automatically slowed down. A value of GET_NONBLOCKING receives as much events as possible without slowing down the producer. GET_ALL is typically used by the logger, while GET_NONBLOCKING is typically used by analyzers.
request_idrequest ID returned by the function. This ID is passed to the callback routine and must be used in the bm_delete_request() routine.
funcallback routine which gets called when an event of the specified type is received.
Returns
BM_SUCCESS, BM_INVALID_HANDLE
BM_NO_MEMORY too many requests. The value MAX_EVENT_REQUESTS in midas.h should be increased.

Definition at line 8485 of file midas.cxx.

8489{
8490 assert(request_id != NULL);
8491
8492 EventRequest r;
8493 r.buffer_handle = buffer_handle;
8494 r.event_id = event_id;
8496 r.dispatcher = func;
8497
8498 {
8499 std::lock_guard<std::mutex> guard(_request_list_mutex);
8500
8501 bool found = false;
8502
8503 // find deleted entry
8504 for (size_t i = 0; i < _request_list.size(); i++) {
8505 if (_request_list[i].buffer_handle == 0) {
8506 _request_list[i] = r;
8507 *request_id = i;
8508 found = true;
8509 break;
8510 }
8511 }
8512
8513 if (!found) { // not found
8514 *request_id = _request_list.size();
8515 _request_list.push_back(r);
8516 }
8517
8518 // implicit unlock()
8519 }
8520
8521 /* add request in buffer structure */
8522 int status = bm_add_event_request(buffer_handle, event_id, trigger_mask, sampling_type, func, *request_id);
8523 if (status != BM_SUCCESS)
8524 return status;
8525
8526 return BM_SUCCESS;
8527}
INT bm_add_event_request(INT buffer_handle, short int event_id, short int trigger_mask, INT sampling_type, EVENT_HANDLER *func, INT request_id)
Definition midas.cxx:8334
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_reset_buffer_locked()

static void bm_reset_buffer_locked ( BUFFER pbuf)
static

Definition at line 6409 of file midas.cxx.

6409 {
6410 BUFFER_HEADER *pheader = pbuf->buffer_header;
6411
6412 //printf("bm_reset_buffer: buffer \"%s\"\n", pheader->name);
6413
6414 pheader->read_pointer = 0;
6415 pheader->write_pointer = 0;
6416
6417 int i;
6418 for (i = 0; i < pheader->max_client_index; i++) {
6419 BUFFER_CLIENT *pc = pheader->client + i;
6420 if (pc->pid) {
6421 pc->read_pointer = 0;
6422 }
6423 }
6424}
Here is the caller graph for this function:

◆ bm_send_event()

INT bm_send_event ( INT  buffer_handle,
const EVENT_HEADER pevent,
int  unused,
int  timeout_msec 
)

Definition at line 9698 of file midas.cxx.

9699{
9700 const DWORD MAX_DATA_SIZE = (0x7FFFFFF0 - 16); // event size computations are not 32-bit clean, limit event size to 2GB. K.O.
9701 const DWORD data_size = pevent->data_size; // 32-bit unsigned value
9702
9703 if (data_size == 0) {
9704 cm_msg(MERROR, "bm_send_event", "invalid event data size zero");
9705 return BM_INVALID_SIZE;
9706 }
9707
9708 if (data_size > MAX_DATA_SIZE) {
9709 cm_msg(MERROR, "bm_send_event", "invalid event data size %d (0x%x) maximum is %d (0x%x)", data_size, data_size, MAX_DATA_SIZE, MAX_DATA_SIZE);
9710 return BM_INVALID_SIZE;
9711 }
9712
9713 const size_t event_size = sizeof(EVENT_HEADER) + data_size;
9714
9715 //printf("bm_send_event: pevent %p, data_size %d, event_size %d, buf_size %d\n", pevent, data_size, event_size, unused);
9716
9717 if (rpc_is_remote()) {
9718 //return bm_send_event_rpc(buffer_handle, pevent, event_size, timeout_msec);
9719 return rpc_send_event_sg(buffer_handle, 1, (char**)&pevent, &event_size);
9720 } else {
9721 return bm_send_event_sg(buffer_handle, 1, (char**)&pevent, &event_size, timeout_msec);
9722 }
9723}
int bm_send_event_sg(int buffer_handle, int sg_n, const char *const sg_ptr[], const size_t sg_len[], int timeout_msec)
Definition midas.cxx:9798
#define BM_INVALID_SIZE
Definition midas.h:624
INT rpc_send_event_sg(INT buffer_handle, int sg_n, const char *const sg_ptr[], const size_t sg_len[])
Definition midas.cxx:14382
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_send_event_sg()

int bm_send_event_sg ( int  buffer_handle,
int  sg_n,
const char *const  sg_ptr[],
const size_t  sg_len[],
int  timeout_msec 
)

Sends an event to a buffer. This function check if the buffer has enough space for the event, then copies the event to the buffer in shared memory. If clients have requests for the event, they are notified via an UDP packet.

char event[1000];
// create event with ID 1, trigger mask 0, size 100 bytes and serial number 1
bm_compose_event((EVENT_HEADER *) event, 1, 0, 100, 1);
// set first byte of event
*(event+sizeof(EVENT_HEADER)) = <...>
#include <stdio.h>
#include "midas.h"
{
HNDLE hbuf;
char event[1000];
status = cm_connect_experiment("", "Sample", "Producer", NULL);
return 1;
// create event with ID 1, trigger mask 0, size 100 bytes and serial number 1
bm_compose_event((EVENT_HEADER *) event, 1, 0, 100, 1);
// set event data
for (i=0 ; i<100 ; i++)
*(event+sizeof(EVENT_HEADER)+i) = i;
// send event
bm_send_event(hbuf, event, 100+sizeof(EVENT_HEADER), BM_WAIT);
return 0;
}
INT bm_send_event(INT buffer_handle, const EVENT_HEADER *pevent, int unused, int timeout_msec)
Definition midas.cxx:9698
Parameters
buffer_handleBuffer handle obtained via bm_open_buffer()
sourceAddress of event buffer
buf_sizeSize of event including event header in bytes
timeout_msecTimeout waiting for free space in the event buffer. If BM_WAIT, wait forever. If BM_NO_WAIT, the function returns immediately with a value of BM_ASYNC_RETURN without writing the event to the buffer
Returns
BM_SUCCESS, BM_INVALID_HANDLE, BM_INVALID_PARAM
BM_ASYNC_RETURN Routine called with timeout_msec == BM_NO_WAIT and buffer has not enough space to receive event
BM_NO_MEMORY Event is too large for network buffer or event buffer. One has to increase the event buffer size "/Experiment/Buffer sizes/SYSTEM" and/or /Experiment/MAX_EVENT_SIZE in ODB.

Definition at line 9798 of file midas.cxx.

9799{
9800 if (rpc_is_remote())
9801 return rpc_send_event_sg(buffer_handle, sg_n, sg_ptr, sg_len);
9802
9803 if (sg_n < 1) {
9804 cm_msg(MERROR, "bm_send_event", "invalid sg_n %d", sg_n);
9805 return BM_INVALID_SIZE;
9806 }
9807
9808 if (sg_ptr[0] == NULL) {
9809 cm_msg(MERROR, "bm_send_event", "invalid sg_ptr[0] is NULL");
9810 return BM_INVALID_SIZE;
9811 }
9812
9813 if (sg_len[0] < sizeof(EVENT_HEADER)) {
9814 cm_msg(MERROR, "bm_send_event", "invalid sg_len[0] value %d is smaller than event header size %d", (int)sg_len[0], (int)sizeof(EVENT_HEADER));
9815 return BM_INVALID_SIZE;
9816 }
9817
9818 const EVENT_HEADER* pevent = (const EVENT_HEADER*)sg_ptr[0];
9819
9820 const DWORD MAX_DATA_SIZE = (0x7FFFFFF0 - 16); // event size computations are not 32-bit clean, limit event size to 2GB. K.O.
9821 const DWORD data_size = pevent->data_size; // 32-bit unsigned value
9822
9823 if (data_size == 0) {
9824 cm_msg(MERROR, "bm_send_event", "invalid event data size zero");
9825 return BM_INVALID_SIZE;
9826 }
9827
9828 if (data_size > MAX_DATA_SIZE) {
9829 cm_msg(MERROR, "bm_send_event", "invalid event data size %d (0x%x) maximum is %d (0x%x)", data_size, data_size, MAX_DATA_SIZE, MAX_DATA_SIZE);
9830 return BM_INVALID_SIZE;
9831 }
9832
9833 const size_t event_size = sizeof(EVENT_HEADER) + data_size;
9834
9835 size_t count = 0;
9836 for (int i=0; i<sg_n; i++) {
9837 count += sg_len[i];
9838 }
9839
9840 if (count != event_size) {
9841 cm_msg(MERROR, "bm_send_event", "data size mismatch: event data_size %d, event_size %d not same as sum of sg_len %d", (int)data_size, (int)event_size, (int)count);
9842 return BM_INVALID_SIZE;
9843 }
9844
9845 //printf("bm_send_event_sg: pevent %p, event_id 0x%04x, serial 0x%08x, data_size %d, event_size %d, total_size %d\n", pevent, pevent->event_id, pevent->serial_number, (int)pevent->data_size, (int)event_size, (int)total_size);
9846
9847#ifdef LOCAL_ROUTINES
9848 {
9849 int status = 0;
9850 const size_t total_size = ALIGN8(event_size);
9851
9852 BUFFER *pbuf = bm_get_buffer("bm_send_event_sg", buffer_handle, &status);
9853
9854 if (!pbuf)
9855 return status;
9856
9857 /* round up total_size to next DWORD boundary */
9858 //int total_size = ALIGN8(event_size);
9859
9860 /* check if write cache is enabled */
9861 if (pbuf->write_cache_size) {
9863
9864 if (status != BM_SUCCESS)
9865 return status;
9866
9867 /* check if write cache is enabled */
9868 if (pbuf->write_cache_size) {
9870 bool too_big = event_size > max_event_size;
9871
9872 //printf("bm_send_event: write %zu/%zu max %zu, cache size %zu, wp %zu\n", event_size, total_size, max_event_size, pbuf->write_cache_size.load(), pbuf->write_cache_wp);
9873
9874 /* if this event does not fit into the write cache, flush the write cache */
9875 if (pbuf->write_cache_wp > 0 && (pbuf->write_cache_wp + total_size > pbuf->write_cache_size || too_big)) {
9876 //printf("bm_send_event: write %zu/%zu but cache is full, size %zu, wp %zu\n", event_size, total_size, pbuf->write_cache_size.load(), pbuf->write_cache_wp);
9877
9878 bm_lock_buffer_guard pbuf_guard(pbuf);
9879
9880 if (!pbuf_guard.is_locked()) {
9881 pbuf->write_cache_mutex.unlock();
9882 return pbuf_guard.get_status();
9883 }
9884
9885 int status = bm_flush_cache_locked(pbuf_guard, timeout_msec);
9886
9887 if (pbuf_guard.is_locked()) {
9888 // check if bm_wait_for_free_space() failed to relock the buffer
9889 pbuf_guard.unlock();
9890 }
9891
9892 if (status != BM_SUCCESS) {
9893 pbuf->write_cache_mutex.unlock();
9894 // bm_flush_cache() failed: timeout in bm_wait_for_free_space() or write cache size is bigger than buffer size or buffer was closed.
9895 if (status == BM_NO_MEMORY)
9896 cm_msg(MERROR, "bm_send_event", "write cache size is bigger than buffer size");
9897 return status;
9898 }
9899
9900 // write cache must be empty here
9901 assert(pbuf->write_cache_wp == 0);
9902 }
9903
9904 /* write this event into the write cache, if it is not too big and if it fits */
9905 if (!too_big && pbuf->write_cache_wp + total_size <= pbuf->write_cache_size) {
9906 //printf("bm_send_event: write %d/%d to cache size %d, wp %d\n", (int)event_size, (int)total_size, (int)pbuf->write_cache_size, (int)pbuf->write_cache_wp);
9907
9908 char* wptr = pbuf->write_cache + pbuf->write_cache_wp;
9909
9910 for (int i=0; i<sg_n; i++) {
9911 memcpy(wptr, sg_ptr[i], sg_len[i]);
9912 wptr += sg_len[i];
9913 }
9914
9915 pbuf->write_cache_wp += total_size;
9916
9917 pbuf->write_cache_mutex.unlock();
9918 return BM_SUCCESS;
9919 }
9920 }
9921
9922 /* event did not fit into the write cache, we flushed the write cache and we send it directly to shared memory */
9923 pbuf->write_cache_mutex.unlock();
9924 }
9925
9926 /* we come here only for events that are too big to fit into the cache */
9927
9928 /* lock the buffer */
9929 bm_lock_buffer_guard pbuf_guard(pbuf);
9930
9931 if (!pbuf_guard.is_locked()) {
9932 return pbuf_guard.get_status();
9933 }
9934
9935 /* calculate some shorthands */
9936 BUFFER_HEADER *pheader = pbuf->buffer_header;
9937
9938#if 0
9940 if (status != BM_SUCCESS) {
9941 printf("bm_send_event: corrupted 111!\n");
9942 abort();
9943 }
9944#endif
9945
9946 /* check if buffer is large enough */
9947 if (total_size >= (size_t)pheader->size) {
9948 pbuf_guard.unlock(); // unlock before cm_msg()
9949 cm_msg(MERROR, "bm_send_event", "total event size (%d) larger than size (%d) of buffer \'%s\'", (int)total_size, pheader->size, pheader->name);
9950 return BM_NO_MEMORY;
9951 }
9952
9953 status = bm_wait_for_free_space_locked(pbuf_guard, timeout_msec, total_size, false);
9954
9955 if (status != BM_SUCCESS) {
9956 // implicit unlock
9957 return status;
9958 }
9959
9960#if 0
9962 if (status != BM_SUCCESS) {
9963 printf("bm_send_event: corrupted 222!\n");
9964 abort();
9965 }
9966#endif
9967
9968 int old_write_pointer = pheader->write_pointer;
9969
9970 bm_write_to_buffer_locked(pheader, sg_n, sg_ptr, sg_len, total_size);
9971
9972 /* write pointer was incremented, but there should
9973 * always be some free space in the buffer and the
9974 * write pointer should never cacth up to the read pointer:
9975 * the rest of the code gets confused this happens (buffer 100% full)
9976 * as it is write_pointer == read_pointer can be either
9977 * 100% full or 100% empty. My solution: never fill
9978 * the buffer to 100% */
9979 assert(pheader->write_pointer != pheader->read_pointer);
9980
9981 /* send wake up messages to all clients that want this event */
9982 int i;
9983 for (i = 0; i < pheader->max_client_index; i++) {
9984 BUFFER_CLIENT *pc = pheader->client + i;
9985 int request_id = bm_find_first_request_locked(pc, pevent);
9986 bm_notify_reader_locked(pheader, pc, old_write_pointer, request_id);
9987 }
9988
9989#if 0
9991 if (status != BM_SUCCESS) {
9992 printf("bm_send_event: corrupted 333!\n");
9993 abort();
9994 }
9995#endif
9996
9997 /* update statistics */
9998 pheader->num_in_events++;
9999 pbuf->count_sent += 1;
10000 pbuf->bytes_sent += total_size;
10001 }
10002#endif /* LOCAL_ROUTINES */
10003
10004 return BM_SUCCESS;
10005}
double count
Definition mdump.cxx:33
INT max_event_size
Definition mfed.cxx:30
#define MAX_WRITE_CACHE_EVENT_SIZE_DIV
Definition midas.h:259
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_send_event_vec() [1/2]

int bm_send_event_vec ( int  buffer_handle,
const std::vector< char > &  event,
int  timeout_msec 
)

Definition at line 9725 of file midas.cxx.

9726{
9727 const char* cptr = event.data();
9728 size_t clen = event.size();
9729 return bm_send_event_sg(buffer_handle, 1, &cptr, &clen, timeout_msec);
9730}
Here is the call graph for this function:

◆ bm_send_event_vec() [2/2]

int bm_send_event_vec ( int  buffer_handle,
const std::vector< std::vector< char > > &  event,
int  timeout_msec 
)

Definition at line 9732 of file midas.cxx.

9733{
9734 int sg_n = event.size();
9735 const char* sg_ptr[sg_n];
9736 size_t sg_len[sg_n];
9737 for (int i=0; i<sg_n; i++) {
9738 sg_ptr[i] = event[i].data();
9739 sg_len[i] = event[i].size();
9740 }
9741 return bm_send_event_sg(buffer_handle, sg_n, sg_ptr, sg_len, timeout_msec);
9742}
Here is the call graph for this function:

◆ bm_set_cache_size()

INT bm_set_cache_size ( INT  buffer_handle,
size_t  read_size,
size_t  write_size 
)

Modifies buffer cache size. Without a buffer cache, events are copied to/from the shared memory event by event.

To protect processed from accessing the shared memory simultaneously, semaphores are used. Since semaphore operations are CPU consuming (typically 50-100us) this can slow down the data transfer especially for small events. By using a cache the number of semaphore operations is reduced dramatically. Instead writing directly to the shared memory, the events are copied to a local cache buffer. When this buffer is full, it is copied to the shared memory in one operation. The same technique can be used when receiving events.

The drawback of this method is that the events have to be copied twice, once to the cache and once from the cache to the shared memory. Therefore it can happen that the usage of a cache even slows down data throughput on a given environment (computer type, OS type, event size). The cache size has therefore be optimized manually to maximize data throughput.

Parameters
buffer_handlebuffer handle obtained via bm_open_buffer()
read_sizecache size for reading events in bytes, zero for no cache
write_sizecache size for writing events in bytes, zero for no cache
Returns
BM_SUCCESS, BM_INVALID_HANDLE, BM_NO_MEMORY, BM_INVALID_PARAM

Definition at line 8160 of file midas.cxx.

8162{
8163 if (rpc_is_remote())
8164 return rpc_call(RPC_BM_SET_CACHE_SIZE, buffer_handle, read_size, write_size);
8165
8166#ifdef LOCAL_ROUTINES
8167 {
8168 int status = 0;
8169
8170 BUFFER *pbuf = bm_get_buffer("bm_set_cache_size", buffer_handle, &status);
8171
8172 if (!pbuf)
8173 return status;
8174
8175 /* lock pbuf for local access. we do not lock buffer semaphore because we do not touch the shared memory */
8176
8178
8179 if (status != BM_SUCCESS)
8180 return status;
8181
8182 if (write_size < 0)
8183 write_size = 0;
8184
8185 if (write_size > 0) {
8186 if (write_size < MIN_WRITE_CACHE_SIZE) {
8187 cm_msg(MERROR, "bm_set_cache_size", "requested write cache size %zu on buffer \"%s\" too small, will use minimum size %d", write_size, pbuf->buffer_name, MIN_WRITE_CACHE_SIZE);
8188 write_size = MIN_WRITE_CACHE_SIZE;
8189 }
8190 }
8191
8192 size_t max_write_size = pbuf->buffer_header->size/MAX_WRITE_CACHE_SIZE_DIV;
8193
8194 if (write_size > max_write_size) {
8195 size_t new_write_size = max_write_size;
8196 cm_msg(MERROR, "bm_set_cache_size", "requested write cache size %zu on buffer \"%s\" is too big: buffer size is %d, write cache size will be %zu bytes", write_size, pbuf->buffer_name, pbuf->buffer_header->size, new_write_size);
8197 write_size = new_write_size;
8198 }
8199
8200 pbuf->buffer_mutex.unlock();
8201
8202 /* resize read cache */
8203
8205
8206 if (status != BM_SUCCESS) {
8207 return status;
8208 }
8209
8210 if (pbuf->read_cache_size > 0) {
8211 free(pbuf->read_cache);
8212 pbuf->read_cache = NULL;
8213 }
8214
8215 if (read_size > 0) {
8216 pbuf->read_cache = (char *) malloc(read_size);
8217 if (pbuf->read_cache == NULL) {
8218 pbuf->read_cache_size = 0;
8219 pbuf->read_cache_rp = 0;
8220 pbuf->read_cache_wp = 0;
8221 pbuf->read_cache_mutex.unlock();
8222 cm_msg(MERROR, "bm_set_cache_size", "not enough memory to allocate read cache for buffer \"%s\", malloc(%zu) failed", pbuf->buffer_name, read_size);
8223 return BM_NO_MEMORY;
8224 }
8225 }
8226
8227 pbuf->read_cache_size = read_size;
8228 pbuf->read_cache_rp = 0;
8229 pbuf->read_cache_wp = 0;
8230
8231 pbuf->read_cache_mutex.unlock();
8232
8233 /* resize the write cache */
8234
8236
8237 if (status != BM_SUCCESS)
8238 return status;
8239
8240 // FIXME: should flush the write cache!
8241 if (pbuf->write_cache_size && pbuf->write_cache_wp > 0) {
8242 cm_msg(MERROR, "bm_set_cache_size", "buffer \"%s\" lost %zu bytes from the write cache", pbuf->buffer_name, pbuf->write_cache_wp);
8243 }
8244
8245 /* manage write cache */
8246 if (pbuf->write_cache_size > 0) {
8247 free(pbuf->write_cache);
8248 pbuf->write_cache = NULL;
8249 }
8250
8251 if (write_size > 0) {
8252 pbuf->write_cache = (char *) M_MALLOC(write_size);
8253 if (pbuf->write_cache == NULL) {
8254 pbuf->write_cache_size = 0;
8255 pbuf->write_cache_rp = 0;
8256 pbuf->write_cache_wp = 0;
8257 pbuf->write_cache_mutex.unlock();
8258 cm_msg(MERROR, "bm_set_cache_size", "not enough memory to allocate write cache for buffer \"%s\", malloc(%zu) failed", pbuf->buffer_name, write_size);
8259 return BM_NO_MEMORY;
8260 }
8261 }
8262
8263 pbuf->write_cache_size = write_size;
8264 pbuf->write_cache_rp = 0;
8265 pbuf->write_cache_wp = 0;
8266
8267 pbuf->write_cache_mutex.unlock();
8268 }
8269#endif /* LOCAL_ROUTINES */
8270
8271 return BM_SUCCESS;
8272}
static int bm_lock_buffer_mutex(BUFFER *pbuf)
Definition midas.cxx:7966
#define RPC_BM_SET_CACHE_SIZE
Definition mrpc.h:42
#define M_MALLOC(x)
Definition midas.h:1535
#define MIN_WRITE_CACHE_SIZE
Definition midas.h:257
#define MAX_WRITE_CACHE_SIZE_DIV
Definition midas.h:258
std::timed_mutex buffer_mutex
Definition midas.h:989
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_skip_event() [1/2]

static int bm_skip_event ( BUFFER pbuf)
static

Definition at line 10981 of file midas.cxx.

10982{
10983 /* clear read cache */
10984 if (pbuf->read_cache_size > 0) {
10985
10987
10988 if (status != BM_SUCCESS)
10989 return status;
10990
10991 pbuf->read_cache_rp = 0;
10992 pbuf->read_cache_wp = 0;
10993
10994 pbuf->read_cache_mutex.unlock();
10995 }
10996
10997 bm_lock_buffer_guard pbuf_guard(pbuf);
10998
10999 if (!pbuf_guard.is_locked())
11000 return pbuf_guard.get_status();
11001
11002 BUFFER_HEADER *pheader = pbuf->buffer_header;
11003
11004 /* forward read pointer to global write pointer */
11005 BUFFER_CLIENT *pclient = bm_get_my_client_locked(pbuf_guard);
11006 pclient->read_pointer = pheader->write_pointer;
11007
11008 return BM_SUCCESS;
11009}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_skip_event() [2/2]

INT bm_skip_event ( INT  buffer_handle)

Skip all events in current buffer.

Useful for single event displays to see the newest events

Parameters
buffer_handleHandle of the buffer. Must be obtained via bm_open_buffer.
Returns
BM_SUCCESS, BM_INVALID_HANDLE, RPC_NET_ERROR

Definition at line 11022 of file midas.cxx.

11022 {
11023 if (rpc_is_remote())
11024 return rpc_call(RPC_BM_SKIP_EVENT, buffer_handle);
11025
11026#ifdef LOCAL_ROUTINES
11027 {
11028 int status = 0;
11029
11030 BUFFER *pbuf = bm_get_buffer("bm_skip_event", buffer_handle, &status);
11031
11032 if (!pbuf)
11033 return status;
11034
11035 return bm_skip_event(pbuf);
11036 }
11037#endif
11038
11039 return BM_SUCCESS;
11040}
#define RPC_BM_SKIP_EVENT
Definition mrpc.h:50
Here is the call graph for this function:

◆ bm_update_last_activity()

static void bm_update_last_activity ( DWORD  millitime)
static

Update last activity time

Definition at line 6135 of file midas.cxx.

6135 {
6136 int pid = ss_getpid();
6137
6138 std::vector<BUFFER*> mybuffers;
6139
6140 gBuffersMutex.lock();
6141 mybuffers = gBuffers;
6142 gBuffersMutex.unlock();
6143
6144 for (BUFFER* pbuf : mybuffers) {
6145 if (!pbuf)
6146 continue;
6147 if (pbuf->attached) {
6148
6149 bm_lock_buffer_guard pbuf_guard(pbuf);
6150
6151 if (!pbuf_guard.is_locked())
6152 continue;
6153
6154 BUFFER_HEADER *pheader = pbuf->buffer_header;
6155 for (int j = 0; j < pheader->max_client_index; j++) {
6156 BUFFER_CLIENT *pclient = pheader->client + j;
6157 if (pclient->pid == pid) {
6158 pclient->last_activity = millitime;
6159 }
6160 }
6161 }
6162 }
6163}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_update_read_pointer_locked()

static BOOL bm_update_read_pointer_locked ( const char *  caller_name,
BUFFER_HEADER pheader 
)
static

Definition at line 8740 of file midas.cxx.

8740 {
8741 assert(caller_name);
8742
8743 /* calculate global read pointer as "minimum" of client read pointers */
8744 int min_rp = pheader->write_pointer;
8745
8746 int i;
8747 for (i = 0; i < pheader->max_client_index; i++) {
8748 BUFFER_CLIENT *pc = pheader->client + i;
8749 if (pc->pid) {
8751
8752#if 0
8753 printf("bm_update_read_pointer: [%s] rp %d, wp %d, size %d, min_rp %d, client [%s] rp %d\n",
8754 pheader->name,
8755 pheader->read_pointer,
8756 pheader->write_pointer,
8757 pheader->size,
8758 min_rp,
8759 pc->name,
8760 pc->read_pointer);
8761#endif
8762
8763 if (pheader->read_pointer <= pheader->write_pointer) {
8764 // normal pointers
8765 if (pc->read_pointer < min_rp)
8766 min_rp = pc->read_pointer;
8767 } else {
8768 // inverted pointers
8769 if (pc->read_pointer <= pheader->write_pointer) {
8770 // clients 3 and 4
8771 if (pc->read_pointer < min_rp)
8772 min_rp = pc->read_pointer;
8773 } else {
8774 // clients 1 and 2
8775 int xptr = pc->read_pointer - pheader->size;
8776 if (xptr < min_rp)
8777 min_rp = xptr;
8778 }
8779 }
8780 }
8781 }
8782
8783 if (min_rp < 0)
8784 min_rp += pheader->size;
8785
8786 assert(min_rp >= 0);
8787 assert(min_rp < pheader->size);
8788
8789 if (min_rp == pheader->read_pointer) {
8790 return FALSE;
8791 }
8792
8793#if 0
8794 printf("bm_update_read_pointer: [%s] rp %d, wp %d, size %d, new_rp %d, moved\n",
8795 pheader->name,
8796 pheader->read_pointer,
8797 pheader->write_pointer,
8798 pheader->size,
8799 min_rp);
8800#endif
8801
8802 pheader->read_pointer = min_rp;
8803
8804 return TRUE;
8805}
static void bm_validate_client_pointers_locked(const BUFFER_HEADER *pheader, BUFFER_CLIENT *pclient)
Definition midas.cxx:8642
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_validate_buffer_locked()

static int bm_validate_buffer_locked ( const BUFFER pbuf)
static

Definition at line 6325 of file midas.cxx.

6325 {
6326 const BUFFER_HEADER *pheader = pbuf->buffer_header;
6327 const char *pdata = (const char *) (pheader + 1);
6328
6329 //printf("bm_validate_buffer: buffer \"%s\"\n", pheader->name);
6330
6331 //printf("size: %d, rp: %d, wp: %d\n", pheader->size, pheader->read_pointer, pheader->write_pointer);
6332
6333 //printf("clients: max: %d, num: %d, MAX_CLIENTS: %d\n", pheader->max_client_index, pheader->num_clients, MAX_CLIENTS);
6334
6335 if (pheader->read_pointer < 0 || pheader->read_pointer >= pheader->size) {
6336 cm_msg(MERROR, "bm_validate_buffer",
6337 "buffer \"%s\" is corrupted: invalid read pointer %d. Size %d, write pointer %d", pheader->name,
6338 pheader->read_pointer, pheader->size, pheader->write_pointer);
6339 return BM_CORRUPTED;
6340 }
6341
6342 if (pheader->write_pointer < 0 || pheader->write_pointer >= pheader->size) {
6343 cm_msg(MERROR, "bm_validate_buffer",
6344 "buffer \"%s\" is corrupted: invalid write pointer %d. Size %d, read pointer %d", pheader->name,
6345 pheader->write_pointer, pheader->size, pheader->read_pointer);
6346 return BM_CORRUPTED;
6347 }
6348
6349 if (!bm_validate_rp("bm_validate_buffer_locked", pheader, pheader->read_pointer)) {
6350 cm_msg(MERROR, "bm_validate_buffer", "buffer \"%s\" is corrupted: read pointer %d is invalid", pheader->name,
6351 pheader->read_pointer);
6352 return BM_CORRUPTED;
6353 }
6354
6355 int rp = pheader->read_pointer;
6356 int rp0 = -1;
6357 while (rp != pheader->write_pointer) {
6358 if (!bm_validate_rp("bm_validate_buffer_locked", pheader, rp)) {
6359 cm_msg(MERROR, "bm_validate_buffer", "buffer \"%s\" is corrupted: invalid rp %d, last good event at rp %d",
6360 pheader->name, rp, rp0);
6361 return BM_CORRUPTED;
6362 }
6363 //bm_print_event(pdata, rp);
6364 int rp1 = bm_next_rp("bm_validate_buffer_locked", pheader, pdata, rp);
6365 if (rp1 < 0) {
6366 cm_msg(MERROR, "bm_validate_buffer",
6367 "buffer \"%s\" is corrupted: invalid event at rp %d, last good event at rp %d", pheader->name, rp, rp0);
6368 return BM_CORRUPTED;
6369 }
6370 rp0 = rp;
6371 rp = rp1;
6372 }
6373
6374 int i;
6375 for (i = 0; i < MAX_CLIENTS; i++) {
6376 const BUFFER_CLIENT *c = &pheader->client[i];
6377 if (c->pid == 0)
6378 continue;
6379 BOOL get_all = FALSE;
6380 int j;
6381 for (j = 0; j < MAX_EVENT_REQUESTS; j++) {
6382 const EVENT_REQUEST *r = &c->event_request[j];
6383 if (!r->valid)
6384 continue;
6385 BOOL xget_all = r->sampling_type == GET_ALL;
6386 get_all = (get_all || xget_all);
6387 //printf("client slot %d: pid %d, name \"%s\", request %d: id %d, valid %d, sampling_type %d, get_all %d\n", i, c->pid, c->name, j, r->id, r->valid, r->sampling_type, xget_all);
6388 }
6389
6390 int rp = c->read_pointer;
6391 int rp0 = -1;
6392 while (rp != pheader->write_pointer) {
6393 //bm_print_event(pdata, rp);
6394 int rp1 = bm_next_rp("bm_validate_buffer_locked", pheader, pdata, rp);
6395 if (rp1 < 0) {
6396 cm_msg(MERROR, "bm_validate_buffer",
6397 "buffer \"%s\" is corrupted for client \"%s\" rp %d: invalid event at rp %d, last good event at rp %d",
6398 pheader->name, c->name, c->read_pointer, rp, rp0);
6399 return BM_CORRUPTED;
6400 }
6401 rp0 = rp;
6402 rp = rp1;
6403 }
6404 }
6405
6406 return BM_SUCCESS;
6407}
static BOOL bm_validate_rp(const char *who, const BUFFER_HEADER *pheader, int rp)
Definition midas.cxx:6207
static int bm_next_rp(const char *who, const BUFFER_HEADER *pheader, const char *pdata, int rp)
Definition midas.cxx:6274
char c
Definition system.cxx:1312
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_validate_client_index_locked()

static int bm_validate_client_index_locked ( bm_lock_buffer_guard pbuf_guard)
static

Definition at line 5940 of file midas.cxx.

5941{
5942 const BUFFER *pbuf = pbuf_guard.get_pbuf();
5943
5944 bool badindex = false;
5945 bool badclient = false;
5946
5947 int idx = pbuf->client_index;
5948
5949 if (idx < 0) {
5950 badindex = true;
5951 } else if (idx > pbuf->buffer_header->max_client_index) {
5952 badindex = true;
5953 } else {
5954 BUFFER_CLIENT *pclient = &pbuf->buffer_header->client[idx];
5955 if (pclient->name[0] == 0)
5956 badclient = true;
5957 else if (pclient->pid != ss_getpid())
5958 badclient = true;
5959
5960 //if (strcmp(pclient->name,"mdump")==0) {
5961 // for (int i=0; i<15; i++) {
5962 // printf("sleep %d\n", i);
5963 // ::sleep(1);
5964 // }
5965 //}
5966 }
5967
5968#if 0
5969 if (badindex) {
5970 printf("bm_validate_client_index: pbuf=%p, buf_name \"%s\", client_index=%d, max_client_index=%d, badindex %d, pid=%d\n",
5971 pbuf, pbuf->buffer_header->name, pbuf->client_index, pbuf->buffer_header->max_client_index,
5972 badindex, ss_getpid());
5973 } else if (badclient) {
5974 printf("bm_validate_client_index: pbuf=%p, buf_name \"%s\", client_index=%d, max_client_index=%d, client_name=\'%s\', client_pid=%d, pid=%d, badclient %d\n",
5975 pbuf, pbuf->buffer_header->name, pbuf->client_index, pbuf->buffer_header->max_client_index,
5976 pbuf->buffer_header->client[idx].name, pbuf->buffer_header->client[idx].pid,
5977 ss_getpid(), badclient);
5978 } else {
5979 printf("bm_validate_client_index: pbuf=%p, buf_name \"%s\", client_index=%d, max_client_index=%d, client_name=\'%s\', client_pid=%d, pid=%d, goodclient\n",
5980 pbuf, pbuf->buffer_header->name, pbuf->client_index, pbuf->buffer_header->max_client_index,
5981 pbuf->buffer_header->client[idx].name, pbuf->buffer_header->client[idx].pid,
5982 ss_getpid());
5983 }
5984#endif
5985
5986 if (badindex || badclient) {
5987 static int prevent_recursion = 1;
5988
5989 if (prevent_recursion) {
5990 prevent_recursion = 0;
5991
5992 if (badindex) {
5993 cm_msg(MERROR, "bm_validate_client_index", "My client index %d in buffer \'%s\' is invalid, max_client_index %d, my pid %d", idx, pbuf->buffer_header->name, pbuf->buffer_header->max_client_index, ss_getpid());
5994 } else {
5995 cm_msg(MERROR, "bm_validate_client_index", "My client index %d in buffer \'%s\' is invalid: client name \'%s\', pid %d should be my pid %d", idx, pbuf->buffer_header->name, pbuf->buffer_header->client[idx].name, pbuf->buffer_header->client[idx].pid, ss_getpid());
5996 }
5997
5998 cm_msg(MERROR, "bm_validate_client_index", "Maybe this client was removed by a timeout. See midas.log. Cannot continue, aborting...");
5999 }
6000
6001 if (badindex) {
6002 fprintf(stderr, "bm_validate_client_index: My client index %d in buffer \'%s\' is invalid, max_client_index %d, my pid %d\n", idx, pbuf->buffer_header->name, pbuf->buffer_header->max_client_index, ss_getpid());
6003 } else {
6004 fprintf(stderr, "bm_validate_client_index: My client index %d in buffer \'%s\' is invalid: client name \'%s\', pid %d should be my pid %d\n", idx, pbuf->buffer_header->name, pbuf->buffer_header->client[idx].name, pbuf->buffer_header->client[idx].pid, ss_getpid());
6005 }
6006
6007 fprintf(stderr, "bm_validate_client_index: Maybe this client was removed by a timeout. See midas.log. Cannot continue, aborting...\n");
6008
6009 pbuf_guard.unlock();
6010
6011 abort();
6012 }
6013
6014 return idx;
6015}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_validate_client_pointers_locked()

static void bm_validate_client_pointers_locked ( const BUFFER_HEADER pheader,
BUFFER_CLIENT pclient 
)
static

Definition at line 8642 of file midas.cxx.

8642 {
8643 assert(pheader->read_pointer >= 0 && pheader->read_pointer <= pheader->size);
8644 assert(pclient->read_pointer >= 0 && pclient->read_pointer <= pheader->size);
8645
8646 if (pheader->read_pointer <= pheader->write_pointer) {
8647
8648 if (pclient->read_pointer < pheader->read_pointer) {
8649 cm_msg(MINFO, "bm_validate_client_pointers",
8650 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, write pointer %d, size %d",
8651 pclient->name,
8652 pheader->name, pclient->read_pointer, pheader->read_pointer, pheader->write_pointer, pheader->size);
8653
8654 pclient->read_pointer = pheader->read_pointer;
8655 }
8656
8657 if (pclient->read_pointer > pheader->write_pointer) {
8658 cm_msg(MINFO, "bm_validate_client_pointers",
8659 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, read pointer %d, size %d",
8660 pclient->name,
8661 pheader->name, pclient->read_pointer, pheader->write_pointer, pheader->read_pointer, pheader->size);
8662
8663 pclient->read_pointer = pheader->write_pointer;
8664 }
8665
8666 } else {
8667
8668 if (pclient->read_pointer < 0) {
8669 cm_msg(MINFO, "bm_validate_client_pointers",
8670 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, write pointer %d, size %d",
8671 pclient->name,
8672 pheader->name, pclient->read_pointer, pheader->read_pointer, pheader->write_pointer, pheader->size);
8673
8674 pclient->read_pointer = pheader->read_pointer;
8675 }
8676
8677 if (pclient->read_pointer >= pheader->size) {
8678 cm_msg(MINFO, "bm_validate_client_pointers",
8679 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, write pointer %d, size %d",
8680 pclient->name,
8681 pheader->name, pclient->read_pointer, pheader->read_pointer, pheader->write_pointer, pheader->size);
8682
8683 pclient->read_pointer = pheader->read_pointer;
8684 }
8685
8686 if (pclient->read_pointer > pheader->write_pointer && pclient->read_pointer < pheader->read_pointer) {
8687 cm_msg(MINFO, "bm_validate_client_pointers",
8688 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, write pointer %d, size %d",
8689 pclient->name,
8690 pheader->name, pclient->read_pointer, pheader->read_pointer, pheader->write_pointer, pheader->size);
8691
8692 pclient->read_pointer = pheader->read_pointer;
8693 }
8694 }
8695}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_validate_rp()

static BOOL bm_validate_rp ( const char *  who,
const BUFFER_HEADER pheader,
int  rp 
)
static

Definition at line 6207 of file midas.cxx.

6207 {
6208 if (rp < 0 || rp > pheader->size) {
6209 cm_msg(MERROR, "bm_validate_rp",
6210 "error: buffer \"%s\" is corrupted: rp %d is invalid. buffer read_pointer %d, write_pointer %d, size %d, called from %s",
6211 pheader->name,
6212 rp,
6213 pheader->read_pointer,
6214 pheader->write_pointer,
6215 pheader->size,
6216 who);
6217 return FALSE;
6218 }
6219
6220 if ((rp + (int) sizeof(EVENT_HEADER)) > pheader->size) {
6221 // note ">" here, has to match bm_incr_rp() and bm_write_to_buffer()
6222 cm_msg(MERROR, "bm_validate_rp",
6223 "error: buffer \"%s\" is corrupted: rp %d plus event header point beyond the end of buffer by %d bytes. buffer read_pointer %d, write_pointer %d, size %d, called from %s",
6224 pheader->name,
6225 rp,
6226 (int) (rp + sizeof(EVENT_HEADER) - pheader->size),
6227 pheader->read_pointer,
6228 pheader->write_pointer,
6229 pheader->size,
6230 who);
6231 return FALSE;
6232 }
6233
6234 return TRUE;
6235}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_wait_for_free_space_locked()

static int bm_wait_for_free_space_locked ( bm_lock_buffer_guard pbuf_guard,
int  timeout_msec,
int  requested_space,
bool  unlock_write_cache 
)
static
  • signal other clients wait mode *‍/
  • validate client index: we could have been removed from the buffer *‍/

Definition at line 9100 of file midas.cxx.

9101{
9102 // return values:
9103 // BM_SUCCESS - have "requested_space" bytes free in the buffer
9104 // BM_CORRUPTED - shared memory is corrupted
9105 // BM_NO_MEMORY - asked for more than buffer size
9106 // BM_ASYNC_RETURN - timeout waiting for free space
9107 // BM_INVALID_HANDLE - buffer was closed (locks released) (via bm_clock_xxx())
9108 // SS_ABORT - we are told to shutdown (locks releases)
9109
9110 int status;
9111 BUFFER* pbuf = pbuf_guard.get_pbuf();
9112 BUFFER_HEADER *pheader = pbuf->buffer_header;
9113 char *pdata = (char *) (pheader + 1);
9114
9115 /* make sure the buffer never completely full:
9116 * read pointer and write pointer would coincide
9117 * and the code cannot tell if it means the
9118 * buffer is 100% full or 100% empty. It will explode
9119 * or lose events */
9120 requested_space += 100;
9121
9122 if (requested_space >= pheader->size)
9123 return BM_NO_MEMORY;
9124
9125 DWORD time_start = ss_millitime();
9126 DWORD time_end = time_start + timeout_msec;
9127
9128 //DWORD blocking_time = 0;
9129 //int blocking_loops = 0;
9130 int blocking_client_index = -1;
9131 char blocking_client_name[NAME_LENGTH];
9132 blocking_client_name[0] = 0;
9133
9134 while (1) {
9135 while (1) {
9136 /* check if enough space in buffer */
9137
9138 int free = pheader->read_pointer - pheader->write_pointer;
9139 if (free <= 0)
9140 free += pheader->size;
9141
9142 //printf("bm_wait_for_free_space: buffer pointers: read: %d, write: %d, free space: %d, bufsize: %d, event size: %d, timeout %d\n", pheader->read_pointer, pheader->write_pointer, free, pheader->size, requested_space, timeout_msec);
9143
9144 if (requested_space < free) { /* note the '<' to avoid 100% filling */
9145 //if (blocking_loops) {
9146 // DWORD wait_time = ss_millitime() - blocking_time;
9147 // printf("blocking client \"%s\", time %d ms, loops %d\n", blocking_client_name, wait_time, blocking_loops);
9148 //}
9149
9150 if (pbuf->wait_start_time != 0) {
9151 DWORD now = ss_millitime();
9152 DWORD wait_time = now - pbuf->wait_start_time;
9153 pbuf->time_write_wait += wait_time;
9154 pbuf->wait_start_time = 0;
9155 int iclient = pbuf->wait_client_index;
9156 //printf("bm_wait_for_free_space: wait ended: wait time %d ms, blocking client index %d\n", wait_time, iclient);
9157 if (iclient >= 0 && iclient < MAX_CLIENTS) {
9158 pbuf->client_count_write_wait[iclient] += 1;
9159 pbuf->client_time_write_wait[iclient] += wait_time;
9160 }
9161 }
9162
9163 //if (blocking_loops > 0) {
9164 // printf("bm_wait_for_free_space: buffer pointers: read: %d, write: %d, free space: %d, bufsize: %d, event size: %d, timeout %d, found space after %d waits\n", pheader->read_pointer, pheader->write_pointer, free, pheader->size, requested_space, timeout_msec, blocking_loops);
9165 //}
9166
9167 return BM_SUCCESS;
9168 }
9169
9170 if (!bm_validate_rp("bm_wait_for_free_space_locked", pheader, pheader->read_pointer)) {
9171 cm_msg(MERROR, "bm_wait_for_free_space",
9172 "error: buffer \"%s\" is corrupted: read_pointer %d, write_pointer %d, size %d, free %d, waiting for %d bytes: read pointer is invalid",
9173 pheader->name,
9174 pheader->read_pointer,
9175 pheader->write_pointer,
9176 pheader->size,
9177 free,
9178 requested_space);
9179 return BM_CORRUPTED;
9180 }
9181
9182 const EVENT_HEADER *pevent = (const EVENT_HEADER *) (pdata + pheader->read_pointer);
9183 int event_size = pevent->data_size + sizeof(EVENT_HEADER);
9184 int total_size = ALIGN8(event_size);
9185
9186#if 0
9187 printf("bm_wait_for_free_space: buffer pointers: read: %d, write: %d, free space: %d, bufsize: %d, event size: %d, blocking event size %d/%d\n", pheader->read_pointer, pheader->write_pointer, free, pheader->size, requested_space, event_size, total_size);
9188#endif
9189
9190 if (pevent->data_size <= 0 || total_size <= 0 || total_size > pheader->size) {
9191 cm_msg(MERROR, "bm_wait_for_free_space",
9192 "error: buffer \"%s\" is corrupted: read_pointer %d, write_pointer %d, size %d, free %d, waiting for %d bytes: read pointer points to an invalid event: data_size %d, event size %d, total_size %d",
9193 pheader->name,
9194 pheader->read_pointer,
9195 pheader->write_pointer,
9196 pheader->size,
9197 free,
9198 requested_space,
9199 pevent->data_size,
9200 event_size,
9201 total_size);
9202 return BM_CORRUPTED;
9203 }
9204
9205 int blocking_client = -1;
9206
9207 int i;
9208 for (i = 0; i < pheader->max_client_index; i++) {
9209 BUFFER_CLIENT *pc = pheader->client + i;
9210 if (pc->pid) {
9211 if (pc->read_pointer == pheader->read_pointer) {
9212 /*
9213 First assume that the client with the "minimum" read pointer
9214 is not really blocking due to a GET_ALL request.
9215 */
9216 BOOL blocking = FALSE;
9217 //int blocking_request_id = -1;
9218
9219 int j;
9220 for (j = 0; j < pc->max_request_index; j++) {
9221 const EVENT_REQUEST *prequest = pc->event_request + j;
9222 if (prequest->valid
9223 && bm_match_event(prequest->event_id, prequest->trigger_mask, pevent)) {
9224 if (prequest->sampling_type & GET_ALL) {
9225 blocking = TRUE;
9226 //blocking_request_id = prequest->id;
9227 break;
9228 }
9229 }
9230 }
9231
9232 //printf("client [%s] blocking %d, request %d\n", pc->name, blocking, blocking_request_id);
9233
9234 if (blocking) {
9235 blocking_client = i;
9236 break;
9237 }
9238
9239 pc->read_pointer = bm_incr_rp_no_check(pheader, pc->read_pointer, total_size);
9240 }
9241 }
9242 } /* client loop */
9243
9244 if (blocking_client >= 0) {
9245 blocking_client_index = blocking_client;
9246 mstrlcpy(blocking_client_name, pheader->client[blocking_client].name, sizeof(blocking_client_name));
9247 //if (!blocking_time) {
9248 // blocking_time = ss_millitime();
9249 //}
9250
9251 //printf("bm_wait_for_free_space: buffer pointers: read: %d, write: %d, free space: %d, bufsize: %d, event size: %d, timeout %d, must wait for more space!\n", pheader->read_pointer, pheader->write_pointer, free, pheader->size, requested_space, timeout_msec);
9252
9253 // from this "break" we go into timeout check and sleep/wait.
9254 break;
9255 }
9256
9257 /* no blocking clients. move the read pointer and again check for free space */
9258
9259 BOOL moved = bm_update_read_pointer_locked("bm_wait_for_free_space", pheader);
9260
9261 if (!moved) {
9262 cm_msg(MERROR, "bm_wait_for_free_space",
9263 "error: buffer \"%s\" is corrupted: read_pointer %d, write_pointer %d, size %d, free %d, waiting for %d bytes: read pointer did not move as expected",
9264 pheader->name,
9265 pheader->read_pointer,
9266 pheader->write_pointer,
9267 pheader->size,
9268 free,
9269 requested_space);
9270 return BM_CORRUPTED;
9271 }
9272
9273 /* we freed one event, loop back to the check for free space */
9274 }
9275
9276 //blocking_loops++;
9277
9278 /* at least one client is blocking */
9279
9280 BUFFER_CLIENT *pc = bm_get_my_client_locked(pbuf_guard);
9281 pc->write_wait = requested_space;
9282
9283 if (pbuf->wait_start_time == 0) {
9284 pbuf->wait_start_time = ss_millitime();
9285 pbuf->count_write_wait++;
9286 if (requested_space > pbuf->max_requested_space)
9287 pbuf->max_requested_space = requested_space;
9288 pbuf->wait_client_index = blocking_client_index;
9289 }
9290
9291 DWORD now = ss_millitime();
9292
9293 //printf("bm_wait_for_free_space: start 0x%08x, now 0x%08x, end 0x%08x, timeout %d, wait %d\n", time_start, now, time_end, timeout_msec, time_end - now);
9294
9295 int sleep_time_msec = 1000;
9296
9297 if (timeout_msec == BM_WAIT) {
9298 // wait forever
9299 } else if (timeout_msec == BM_NO_WAIT) {
9300 // no wait
9301 return BM_ASYNC_RETURN;
9302 } else {
9303 // check timeout
9304 if (now >= time_end) {
9305 // timeout!
9306 return BM_ASYNC_RETURN;
9307 }
9308
9309 sleep_time_msec = time_end - now;
9310
9311 if (sleep_time_msec <= 0) {
9312 sleep_time_msec = 10;
9313 } else if (sleep_time_msec > 1000) {
9314 sleep_time_msec = 1000;
9315 }
9316 }
9317
9319
9320 /* before waiting, unlock everything in the correct order */
9321
9322 pbuf_guard.unlock();
9323
9324 if (unlock_write_cache)
9325 pbuf->write_cache_mutex.unlock();
9326
9327 //printf("bm_wait_for_free_space: blocking client \"%s\"\n", blocking_client_name);
9328
9329#ifdef DEBUG_MSG
9330 cm_msg(MDEBUG, "Send sleep: rp=%d, wp=%d, level=%1.1lf", pheader->read_pointer, pheader->write_pointer, 100 - 100.0 * size / pheader->size);
9331#endif
9332
9334 //int idx = bm_validate_client_index_locked(pbuf, FALSE);
9335 //if (idx >= 0)
9336 // pheader->client[idx].write_wait = requested_space;
9337
9338 //bm_cleanup("bm_wait_for_free_space", ss_millitime(), FALSE);
9339
9340 status = ss_suspend(sleep_time_msec, MSG_BM);
9341
9342 /* we are told to shutdown */
9343 if (status == SS_ABORT) {
9344 // NB: buffer is locked!
9345 return SS_ABORT;
9346 }
9347
9348 /* make sure we do sleep in this loop:
9349 * if we are the mserver receiving data on the event
9350 * socket and the data buffer is full, ss_suspend() will
9351 * never sleep: it will detect data on the event channel,
9352 * call rpc_server_receive() (recursively, we already *are* in
9353 * rpc_server_receive()) and return without sleeping. Result
9354 * is a busy loop waiting for free space in data buffer */
9355
9356 /* update May 2021: ss_suspend(MSG_BM) no longer looks at
9357 * the event socket, and should sleep now, so this sleep below
9358 * maybe is not needed now. but for safety, I keep it. K.O. */
9359
9360 if (status != SS_TIMEOUT) {
9361 //printf("ss_suspend: status %d\n", status);
9362 ss_sleep(1);
9363 }
9364
9365 /* we may be stuck in this loop for an arbitrary long time,
9366 * depending on how other buffer clients read the accumulated data
9367 * so we should update all the timeouts & etc. K.O. */
9368
9370
9371 /* lock things again in the correct order */
9372
9373 if (unlock_write_cache) {
9375
9376 if (status != BM_SUCCESS) {
9377 // bail out with all locks released
9378 return status;
9379 }
9380 }
9381
9382 if (!pbuf_guard.relock()) {
9383 if (unlock_write_cache) {
9384 pbuf->write_cache_mutex.unlock();
9385 }
9386
9387 // bail out with all locks released
9388 return pbuf_guard.get_status();
9389 }
9390
9391 /* revalidate the client index: we could have been removed from the buffer while sleeping */
9392 pc = bm_get_my_client_locked(pbuf_guard);
9393
9394 pc->write_wait = 0;
9395
9397 //idx = bm_validate_client_index_locked(pbuf, FALSE);
9398 //if (idx >= 0)
9399 // pheader->client[idx].write_wait = 0;
9400 //else {
9401 // cm_msg(MERROR, "bm_wait_for_free_space", "our client index is no longer valid, exiting...");
9402 // status = SS_ABORT;
9403 //}
9404
9405#ifdef DEBUG_MSG
9406 cm_msg(MDEBUG, "Send woke up: rp=%d, wp=%d, level=%1.1lf", pheader->read_pointer, pheader->write_pointer, 100 - 100.0 * size / pheader->size);
9407#endif
9408
9409 }
9410}
int get_status() const
Definition midas.cxx:3192
static BOOL bm_update_read_pointer_locked(const char *caller_name, BUFFER_HEADER *pheader)
Definition midas.cxx:8740
INT cm_periodic_tasks()
Definition midas.cxx:5597
#define SS_TIMEOUT
Definition midas.h:675
#define MDEBUG
Definition midas.h:561
#define MSG_BM
Definition msystem.h:302
INT ss_suspend(INT millisec, INT msg)
Definition system.cxx:4622
INT ss_sleep(INT millisec)
Definition system.cxx:3707
int max_requested_space
Definition midas.h:1020
int count_write_wait
Definition midas.h:1015
int wait_client_index
Definition midas.h:1019
DWORD time_write_wait
Definition midas.h:1016
DWORD wait_start_time
Definition midas.h:1018
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_wait_for_more_events_locked()

static int bm_wait_for_more_events_locked ( bm_lock_buffer_guard pbuf_guard,
BUFFER_CLIENT pc,
int  timeout_msec,
BOOL  unlock_read_cache 
)
static

Definition at line 9412 of file midas.cxx.

9413{
9414 BUFFER* pbuf = pbuf_guard.get_pbuf();
9415 BUFFER_HEADER* pheader = pbuf->buffer_header;
9416
9417 //printf("bm_wait_for_more_events_locked: [%s] timeout %d\n", pheader->name, timeout_msec);
9418
9419 if (pc->read_pointer != pheader->write_pointer) {
9420 // buffer has data
9421 return BM_SUCCESS;
9422 }
9423
9424 if (timeout_msec == BM_NO_WAIT) {
9425 /* event buffer is empty and we are told to not wait */
9426 if (!pc->read_wait) {
9427 //printf("bm_wait_for_more_events: buffer [%s] client [%s] set read_wait in BM_NO_WAIT!\n", pheader->name, pc->name);
9428 pc->read_wait = TRUE;
9429 }
9430 return BM_ASYNC_RETURN;
9431 }
9432
9433 DWORD time_start = ss_millitime();
9434 DWORD time_wait = time_start + timeout_msec;
9435 DWORD sleep_time = 1000;
9436 if (timeout_msec == BM_NO_WAIT) {
9437 // default sleep time
9438 } else if (timeout_msec == BM_WAIT) {
9439 // default sleep time
9440 } else {
9441 if (sleep_time > (DWORD)timeout_msec)
9442 sleep_time = timeout_msec;
9443 }
9444
9445 //printf("time start 0x%08x, end 0x%08x, sleep %d\n", time_start, time_wait, sleep_time);
9446
9447 while (pc->read_pointer == pheader->write_pointer) {
9448 /* wait until there is data in the buffer (write pointer moves) */
9449
9450 if (!pc->read_wait) {
9451 //printf("bm_wait_for_more_events: buffer [%s] client [%s] set read_wait!\n", pheader->name, pc->name);
9452 pc->read_wait = TRUE;
9453 }
9454
9456
9458
9459 // NB: locking order is: 1st read cache lock, 2nd buffer lock, unlock in reverse order
9460
9461 pbuf_guard.unlock();
9462
9463 if (unlock_read_cache)
9464 pbuf->read_cache_mutex.unlock();
9465
9466 int status = ss_suspend(sleep_time, MSG_BM);
9467
9468 if (timeout_msec == BM_NO_WAIT) {
9469 // return immediately
9470 } else if (timeout_msec == BM_WAIT) {
9471 // wait forever
9472 } else {
9473 DWORD now = ss_millitime();
9474 //printf("check timeout: now 0x%08x, end 0x%08x, diff %d\n", now, time_wait, time_wait - now);
9475 if (now >= time_wait) {
9476 timeout_msec = BM_NO_WAIT; // cause immediate return
9477 } else {
9478 sleep_time = time_wait - now;
9479 if (sleep_time > 1000)
9480 sleep_time = 1000;
9481 //printf("time start 0x%08x, now 0x%08x, end 0x%08x, sleep %d\n", time_start, now, time_wait, sleep_time);
9482 }
9483 }
9484
9485 // NB: locking order is: 1st read cache lock, 2nd buffer lock, unlock in reverse order
9486
9487 if (unlock_read_cache) {
9489 if (status != BM_SUCCESS) {
9490 // bail out with all locks released
9491 return status;
9492 }
9493 }
9494
9495 if (!pbuf_guard.relock()) {
9496 if (unlock_read_cache) {
9497 pbuf->read_cache_mutex.unlock();
9498 }
9499 // bail out with all locks released
9500 return pbuf_guard.get_status();
9501 }
9502
9503 /* need to revalidate our BUFFER_CLIENT after releasing the buffer lock
9504 * because we may have been removed from the buffer by bm_cleanup() & co
9505 * due to a timeout or whatever. */
9506 pc = bm_get_my_client_locked(pbuf_guard);
9507
9508 /* return if TCP connection broken */
9509 if (status == SS_ABORT)
9510 return SS_ABORT;
9511
9512 if (timeout_msec == BM_NO_WAIT)
9513 return BM_ASYNC_RETURN;
9514 }
9515
9516 if (pc->read_wait) {
9517 //printf("bm_wait_for_more_events: buffer [%s] client [%s] clear read_wait!\n", pheader->name, pc->name);
9518 pc->read_wait = FALSE;
9519 }
9520
9521 return BM_SUCCESS;
9522}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_wakeup_producers_locked()

static void bm_wakeup_producers_locked ( const BUFFER_HEADER pheader,
const BUFFER_CLIENT pc 
)
static

Definition at line 8807 of file midas.cxx.

8807 {
8808 int i;
8809 int have_get_all_requests = 0;
8810
8811 for (i = 0; i < pc->max_request_index; i++)
8812 if (pc->event_request[i].valid)
8813 have_get_all_requests |= (pc->event_request[i].sampling_type == GET_ALL);
8814
8815 /* only GET_ALL requests actually free space in the event buffer */
8816 if (!have_get_all_requests)
8817 return;
8818
8819 /*
8820 If read pointer has been changed, it may have freed up some space
8821 for waiting producers. So check if free space is now more than 50%
8822 of the buffer size and wake waiting producers.
8823 */
8824
8825 int free_space = pc->read_pointer - pheader->write_pointer;
8826 if (free_space <= 0)
8827 free_space += pheader->size;
8828
8829 if (free_space >= pheader->size * 0.5) {
8830 for (i = 0; i < pheader->max_client_index; i++) {
8831 const BUFFER_CLIENT *pc = pheader->client + i;
8832 if (pc->pid && pc->write_wait) {
8833 BOOL send_wakeup = (pc->write_wait < free_space);
8834 //printf("bm_wakeup_producers: buffer [%s] client [%s] write_wait %d, free_space %d, sending wakeup message %d\n", pheader->name, pc->name, pc->write_wait, free_space, send_wakeup);
8835 if (send_wakeup) {
8836 ss_resume(pc->port, "B ");
8837 }
8838 }
8839 }
8840 }
8841}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_write_buffer_statistics_to_odb()

static void bm_write_buffer_statistics_to_odb ( HNDLE  hDB,
BUFFER pbuf,
BOOL  force 
)
static

Definition at line 6597 of file midas.cxx.

6598{
6599 //printf("bm_buffer_write_statistics_to_odb: buffer [%s] client [%s], lock count %d -> %d, force %d\n", pbuf->buffer_name, pbuf->client_name, pbuf->last_count_lock, pbuf->count_lock, force);
6600
6601 bm_lock_buffer_guard pbuf_guard(pbuf);
6602
6603 if (!pbuf_guard.is_locked())
6604 return;
6605
6606 if (!force) {
6607 if (pbuf->count_lock == pbuf->last_count_lock) {
6608 return;
6609 }
6610 }
6611
6612 std::string buffer_name = pbuf->buffer_name;
6613 std::string client_name = pbuf->client_name;
6614
6615 if ((strlen(buffer_name.c_str()) < 1) || (strlen(client_name.c_str()) < 1)) {
6616 // do not call cm_msg() while holding buffer lock, if we are SYSMSG, we will deadlock. K.O.
6617 pbuf_guard.unlock(); // unlock before cm_msg()
6618 cm_msg(MERROR, "bm_write_buffer_statistics_to_odb", "Invalid empty buffer name \"%s\" or client name \"%s\"", buffer_name.c_str(), client_name.c_str());
6619 return;
6620 }
6621
6622 pbuf->last_count_lock = pbuf->count_lock;
6623
6624 BUFFER_INFO xbuf(pbuf);
6625 BUFFER_HEADER xheader = *pbuf->buffer_header;
6626 int client_index = pbuf->client_index;
6627
6628 pbuf_guard.unlock();
6629
6630 bm_write_buffer_statistics_to_odb_copy(hDB, buffer_name.c_str(), client_name.c_str(), client_index, &xbuf, &xheader);
6631}
static void bm_write_buffer_statistics_to_odb_copy(HNDLE hDB, const char *buffer_name, const char *client_name, int client_index, BUFFER_INFO *pbuf, BUFFER_HEADER *pheader)
Definition midas.cxx:6475
int last_count_lock
Definition midas.h:1017
int count_lock
Definition midas.h:1012
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_write_buffer_statistics_to_odb_copy()

static void bm_write_buffer_statistics_to_odb_copy ( HNDLE  hDB,
const char *  buffer_name,
const char *  client_name,
int  client_index,
BUFFER_INFO pbuf,
BUFFER_HEADER pheader 
)
static

Definition at line 6475 of file midas.cxx.

6476{
6477 int status;
6478
6479 DWORD now = ss_millitime();
6480
6481 HNDLE hKey;
6482 status = db_find_key(hDB, 0, "/System/Buffers", &hKey);
6483 if (status != DB_SUCCESS) {
6484 db_create_key(hDB, 0, "/System/Buffers", TID_KEY);
6485 status = db_find_key(hDB, 0, "/System/Buffers", &hKey);
6486 if (status != DB_SUCCESS)
6487 return;
6488 }
6489
6490 HNDLE hKeyBuffer;
6491 status = db_find_key(hDB, hKey, buffer_name, &hKeyBuffer);
6492 if (status != DB_SUCCESS) {
6494 status = db_find_key(hDB, hKey, buffer_name, &hKeyBuffer);
6495 if (status != DB_SUCCESS)
6496 return;
6497 }
6498
6499 double buf_size = pheader->size;
6500 double buf_rptr = pheader->read_pointer;
6501 double buf_wptr = pheader->write_pointer;
6502
6503 double buf_fill = 0;
6504 double buf_cptr = 0;
6505 double buf_cused = 0;
6506 double buf_cused_pct = 0;
6507
6508 if (client_index >= 0 && client_index <= pheader->max_client_index) {
6509 buf_cptr = pheader->client[client_index].read_pointer;
6510
6511 if (buf_wptr == buf_cptr) {
6512 buf_cused = 0;
6513 } else if (buf_wptr > buf_cptr) {
6514 buf_cused = buf_wptr - buf_cptr;
6515 } else {
6516 buf_cused = (buf_size - buf_cptr) + buf_wptr;
6517 }
6518
6519 buf_cused_pct = buf_cused / buf_size * 100.0;
6520
6521 // we cannot write buf_cused and buf_cused_pct into the buffer statistics
6522 // because some other GET_ALL client may have different buf_cused & etc,
6523 // so they must be written into the per-client statistics
6524 // and the web page should look at all the GET_ALL clients and used
6525 // the biggest buf_cused as the whole-buffer "bytes used" value.
6526 }
6527
6528 if (buf_wptr == buf_rptr) {
6529 buf_fill = 0;
6530 } else if (buf_wptr > buf_rptr) {
6531 buf_fill = buf_wptr - buf_rptr;
6532 } else {
6533 buf_fill = (buf_size - buf_rptr) + buf_wptr;
6534 }
6535
6536 double buf_fill_pct = buf_fill / buf_size * 100.0;
6537
6538 db_set_value(hDB, hKeyBuffer, "Size", &buf_size, sizeof(double), 1, TID_DOUBLE);
6539 db_set_value(hDB, hKeyBuffer, "Write pointer", &buf_wptr, sizeof(double), 1, TID_DOUBLE);
6540 db_set_value(hDB, hKeyBuffer, "Read pointer", &buf_rptr, sizeof(double), 1, TID_DOUBLE);
6541 db_set_value(hDB, hKeyBuffer, "Filled", &buf_fill, sizeof(double), 1, TID_DOUBLE);
6542 db_set_value(hDB, hKeyBuffer, "Filled pct", &buf_fill_pct, sizeof(double), 1, TID_DOUBLE);
6543
6544 status = db_find_key(hDB, hKeyBuffer, "Clients", &hKey);
6545 if (status != DB_SUCCESS) {
6546 db_create_key(hDB, hKeyBuffer, "Clients", TID_KEY);
6547 status = db_find_key(hDB, hKeyBuffer, "Clients", &hKey);
6548 if (status != DB_SUCCESS)
6549 return;
6550 }
6551
6552 HNDLE hKeyClient;
6553 status = db_find_key(hDB, hKey, client_name, &hKeyClient);
6554 if (status != DB_SUCCESS) {
6555 db_create_key(hDB, hKey, client_name, TID_KEY);
6556 status = db_find_key(hDB, hKey, client_name, &hKeyClient);
6557 if (status != DB_SUCCESS)
6558 return;
6559 }
6560
6561 db_set_value(hDB, hKeyClient, "count_lock", &pbuf->count_lock, sizeof(int), 1, TID_INT32);
6562 db_set_value(hDB, hKeyClient, "count_sent", &pbuf->count_sent, sizeof(int), 1, TID_INT32);
6563 db_set_value(hDB, hKeyClient, "bytes_sent", &pbuf->bytes_sent, sizeof(double), 1, TID_DOUBLE);
6564 db_set_value(hDB, hKeyClient, "count_write_wait", &pbuf->count_write_wait, sizeof(int), 1, TID_INT32);
6565 db_set_value(hDB, hKeyClient, "time_write_wait", &pbuf->time_write_wait, sizeof(DWORD), 1, TID_UINT32);
6566 db_set_value(hDB, hKeyClient, "max_bytes_write_wait", &pbuf->max_requested_space, sizeof(INT), 1, TID_INT32);
6567 db_set_value(hDB, hKeyClient, "count_read", &pbuf->count_read, sizeof(int), 1, TID_INT32);
6568 db_set_value(hDB, hKeyClient, "bytes_read", &pbuf->bytes_read, sizeof(double), 1, TID_DOUBLE);
6569 db_set_value(hDB, hKeyClient, "get_all_flag", &pbuf->get_all_flag, sizeof(BOOL), 1, TID_BOOL);
6570 db_set_value(hDB, hKeyClient, "read_pointer", &buf_cptr, sizeof(double), 1, TID_DOUBLE);
6571 db_set_value(hDB, hKeyClient, "bytes_used", &buf_cused, sizeof(double), 1, TID_DOUBLE);
6572 db_set_value(hDB, hKeyClient, "pct_used", &buf_cused_pct, sizeof(double), 1, TID_DOUBLE);
6573
6574 for (int i = 0; i < MAX_CLIENTS; i++) {
6575 if (!pbuf->client_count_write_wait[i])
6576 continue;
6577
6578 if (pheader->client[i].pid == 0)
6579 continue;
6580
6581 if (pheader->client[i].name[0] == 0)
6582 continue;
6583
6584 char str[100 + NAME_LENGTH];
6585
6586 sprintf(str, "writes_blocked_by/%s/count_write_wait", pheader->client[i].name);
6587 db_set_value(hDB, hKeyClient, str, &pbuf->client_count_write_wait[i], sizeof(int), 1, TID_INT32);
6588
6589 sprintf(str, "writes_blocked_by/%s/time_write_wait", pheader->client[i].name);
6590 db_set_value(hDB, hKeyClient, str, &pbuf->client_time_write_wait[i], sizeof(DWORD), 1, TID_UINT32);
6591 }
6592
6593 db_set_value(hDB, hKeyBuffer, "Last updated", &now, sizeof(DWORD), 1, TID_UINT32);
6594 db_set_value(hDB, hKeyClient, "last_updated", &now, sizeof(DWORD), 1, TID_UINT32);
6595}
#define TID_DOUBLE
Definition midas.h:343
#define TID_KEY
Definition midas.h:349
#define TID_BOOL
Definition midas.h:340
#define TID_INT32
Definition midas.h:339
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition odb.cxx:3887
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
Definition odb.cxx:5523
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4751
HNDLE hKey
int count_sent
Definition midas.cxx:6438
BOOL get_all_flag
Definition midas.cxx:6434
int count_lock
Definition midas.cxx:6437
int count_write_wait
Definition midas.cxx:6440
double bytes_read
Definition midas.cxx:6447
int client_count_write_wait[MAX_CLIENTS]
Definition midas.cxx:6448
DWORD time_write_wait
Definition midas.cxx:6441
int count_read
Definition midas.cxx:6446
double bytes_sent
Definition midas.cxx:6439
DWORD client_time_write_wait[MAX_CLIENTS]
Definition midas.cxx:6449
int max_requested_space
Definition midas.cxx:6445
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_write_statistics_to_odb()

INT bm_write_statistics_to_odb ( void  )

Close all open buffers

Returns
BM_SUCCESS

Definition at line 7300 of file midas.cxx.

7300 {
7301#ifdef LOCAL_ROUTINES
7302 {
7303 int status;
7304 HNDLE hDB;
7305
7307
7308 if (status != CM_SUCCESS) {
7309 //printf("bm_write_statistics_to_odb: cannot get ODB handle!\n");
7310 return BM_SUCCESS;
7311 }
7312
7313 std::vector<BUFFER*> mybuffers;
7314
7315 gBuffersMutex.lock();
7316 mybuffers = gBuffers;
7317 gBuffersMutex.unlock();
7318
7319 for (BUFFER* pbuf : mybuffers) {
7320 if (!pbuf || !pbuf->attached)
7321 continue;
7323 }
7324 }
7325#endif /* LOCAL_ROUTINES */
7326
7327 return BM_SUCCESS;
7328}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bm_write_to_buffer_locked()

static void bm_write_to_buffer_locked ( BUFFER_HEADER pheader,
int  sg_n,
const char *const  sg_ptr[],
const size_t  sg_len[],
size_t  total_size 
)
static

Definition at line 9524 of file midas.cxx.

9525{
9526 char *pdata = (char *) (pheader + 1);
9527
9528 //int old_write_pointer = pheader->write_pointer;
9529
9530 /* new event fits into the remaining space? */
9531 if ((size_t)pheader->write_pointer + total_size <= (size_t)pheader->size) {
9532 //memcpy(pdata + pheader->write_pointer, pevent, event_size);
9533 char* wptr = pdata + pheader->write_pointer;
9534 for (int i=0; i<sg_n; i++) {
9535 //printf("memcpy %p+%d\n", sg_ptr[i], (int)sg_len[i]);
9536 memcpy(wptr, sg_ptr[i], sg_len[i]);
9537 wptr += sg_len[i];
9538 }
9539 pheader->write_pointer = pheader->write_pointer + total_size;
9540 assert(pheader->write_pointer <= pheader->size);
9541 /* remaining space is smaller than size of an event header? */
9542 if ((pheader->write_pointer + (int) sizeof(EVENT_HEADER)) > pheader->size) {
9543 // note: ">" here to match "bm_incr_rp". If remaining space is exactly
9544 // equal to the event header size, we will write the next event header here,
9545 // then wrap the pointer and write the event data at the beginning of the buffer.
9546 //printf("bm_write_to_buffer_locked: truncate wp %d. buffer size %d, remaining %d, event header size %d, event size %d, total size %d\n", pheader->write_pointer, pheader->size, pheader->size-pheader->write_pointer, (int)sizeof(EVENT_HEADER), event_size, total_size);
9547 pheader->write_pointer = 0;
9548 }
9549 } else {
9550 /* split event */
9551 size_t size = pheader->size - pheader->write_pointer;
9552
9553 //printf("split: wp %d, size %d, avail %d\n", pheader->write_pointer, pheader->size, size);
9554
9555 //memcpy(pdata + pheader->write_pointer, pevent, size);
9556 //memcpy(pdata, ((const char *) pevent) + size, event_size - size);
9557
9558 char* wptr = pdata + pheader->write_pointer;
9559 size_t count = 0;
9560
9561 // copy first part
9562
9563 int i = 0;
9564 for (; i<sg_n; i++) {
9565 if (count + sg_len[i] > size)
9566 break;
9567 memcpy(wptr, sg_ptr[i], sg_len[i]);
9568 wptr += sg_len[i];
9569 count += sg_len[i];
9570 }
9571
9572 //printf("wptr %d, count %d\n", wptr-pdata, count);
9573
9574 // split segment
9575
9576 size_t first = size - count;
9577 size_t second = sg_len[i] - first;
9578 assert(first + second == sg_len[i]);
9579 assert(count + first == size);
9580
9581 //printf("first %d, second %d\n", first, second);
9582
9583 memcpy(wptr, sg_ptr[i], first);
9584 wptr = pdata + 0;
9585 count += first;
9586 memcpy(wptr, sg_ptr[i] + first, second);
9587 wptr += second;
9588 count += second;
9589 i++;
9590
9591 // copy remaining
9592
9593 for (; i<sg_n; i++) {
9594 memcpy(wptr, sg_ptr[i], sg_len[i]);
9595 wptr += sg_len[i];
9596 count += sg_len[i];
9597 }
9598
9599 //printf("wptr %d, count %d\n", wptr-pdata, count);
9600
9601 //printf("bm_write_to_buffer_locked: wrap wp %d -> %d. buffer size %d, available %d, wrote %d, remaining %d, event size %d, total size %d\n", pheader->write_pointer, total_size-size, pheader->size, pheader->size-pheader->write_pointer, size, pheader->size - (pheader->write_pointer+size), event_size, total_size);
9602
9603 pheader->write_pointer = total_size - size;
9604 }
9605
9606 //printf("bm_write_to_buffer_locked: buf [%s] size %d, wrote %d/%d, wp %d -> %d\n", pheader->name, pheader->size, event_size, total_size, old_write_pointer, pheader->write_pointer);
9607}
Here is the caller graph for this function:

Variable Documentation

◆ _bm_lock_timeout

int _bm_lock_timeout = 5 * 60 * 1000
static

Definition at line 5937 of file midas.cxx.

◆ _bm_max_event_size

DWORD _bm_max_event_size = 0
static

Definition at line 5932 of file midas.cxx.

◆ _bm_mutex_timeout_sec

double _bm_mutex_timeout_sec = _bm_lock_timeout/1000 + 15.000
static

Definition at line 5938 of file midas.cxx.

◆ defrag_buffer

EVENT_DEFRAG_BUFFER defrag_buffer[MAX_DEFRAG_EVENTS]
static

Definition at line 11429 of file midas.cxx.