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 11513 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 8427 of file midas.cxx.

8471{
8472 if (rpc_is_remote())
8473 return rpc_call(RPC_BM_ADD_EVENT_REQUEST, buffer_handle, event_id,
8474 trigger_mask, sampling_type, (INT) (POINTER_T) func, request_id);
8475
8476#ifdef LOCAL_ROUTINES
8477 {
8478 int status = 0;
8479
8480 BUFFER *pbuf = bm_get_buffer("bm_add_event_request", buffer_handle, &status);
8481
8482 if (!pbuf)
8483 return status;
8484
8485 /* lock buffer */
8486 bm_lock_buffer_guard pbuf_guard(pbuf);
8487
8488 if (!pbuf_guard.is_locked())
8489 return pbuf_guard.get_status();
8490
8491 /* avoid callback/non callback requests */
8492 if (func == NULL && pbuf->callback) {
8493 pbuf_guard.unlock(); // unlock before cm_msg()
8494 cm_msg(MERROR, "bm_add_event_request", "mixing callback/non callback requests not possible");
8495 return BM_INVALID_MIXING;
8496 }
8497
8498 /* do not allow GET_RECENT with nonzero cache size */
8499 if (sampling_type == GET_RECENT && pbuf->read_cache_size > 0) {
8500 pbuf_guard.unlock(); // unlock before cm_msg()
8501 cm_msg(MERROR, "bm_add_event_request", "GET_RECENT request not possible if read cache is enabled");
8502 return BM_INVALID_PARAM;
8503 }
8504
8505 /* get a pointer to the proper client structure */
8506 BUFFER_CLIENT *pclient = bm_get_my_client_locked(pbuf_guard);
8507
8508 /* look for a empty request entry */
8509 int i;
8510 for (i = 0; i < MAX_EVENT_REQUESTS; i++)
8511 if (!pclient->event_request[i].valid)
8512 break;
8513
8514 if (i == MAX_EVENT_REQUESTS) {
8515 // implicit unlock
8516 return BM_NO_MEMORY;
8517 }
8518
8519 /* setup event_request structure */
8520 pclient->event_request[i].id = request_id;
8521 pclient->event_request[i].valid = TRUE;
8522 pclient->event_request[i].event_id = event_id;
8524 pclient->event_request[i].sampling_type = sampling_type;
8525
8526 pclient->all_flag = pclient->all_flag || (sampling_type & GET_ALL);
8527
8528 pbuf->get_all_flag = pclient->all_flag;
8529
8530 /* set callback flag in buffer structure */
8531 if (func != NULL)
8532 pbuf->callback = TRUE;
8533
8534 /*
8535 Save the index of the last request in the list so that later only the
8536 requests 0..max_request_index-1 have to be searched through.
8537 */
8538
8539 if (i + 1 > pclient->max_request_index)
8540 pclient->max_request_index = i + 1;
8541 }
8542#endif /* LOCAL_ROUTINES */
8543
8544 return BM_SUCCESS;
8545}
static BUFFER_CLIENT * bm_get_my_client_locked(bm_lock_buffer_guard &pbuf_guard)
Definition midas.cxx:6071
static BUFFER * bm_get_buffer(const char *who, INT buffer_handle, int *pstatus)
Definition midas.cxx:6687
#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:939
#define RPC_BM_ADD_EVENT_REQUEST
Definition mrpc.h:43
bool rpc_is_remote(void)
Definition midas.cxx:12994
INT rpc_call(DWORD routine_id,...)
Definition midas.cxx:14217
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 11195 of file midas.cxx.

11195 {
11196#ifdef LOCAL_ROUTINES
11197 {
11198 INT status = 0;
11199 BOOL bMore;
11200 DWORD start_time;
11201 //static DWORD last_time = 0;
11202
11203 /* if running as a server, buffer checking is done by client
11204 via ASYNC bm_receive_event */
11205 if (rpc_is_mserver()) {
11206 return FALSE;
11207 }
11208
11209 bMore = FALSE;
11210 start_time = ss_millitime();
11211
11212 std::vector<BUFFER*> mybuffers;
11213
11214 gBuffersMutex.lock();
11215 mybuffers = gBuffers;
11216 gBuffersMutex.unlock();
11217
11218 /* go through all buffers */
11219 for (size_t idx = 0; idx < mybuffers.size(); idx++) {
11220 BUFFER* pbuf = mybuffers[idx];
11221
11222 if (!pbuf || !pbuf->attached)
11223 continue;
11224
11225 //int count_loops = 0;
11226 while (1) {
11227 if (pbuf->attached) {
11228 /* one bm_push_event could cause a run stop and a buffer close, which
11229 * would crash the next call to bm_push_event(). So check for valid
11230 * buffer on each call */
11231
11232 /* this is what happens:
11233 * bm_push_buffer() may call a user callback function
11234 * user callback function may indirectly call bm_close() of this buffer,
11235 * i.e. if it stops the run,
11236 * bm_close() will set pbuf->attached to false, but will not delete pbuf or touch gBuffers
11237 * here we will see pbuf->attched is false and quit this loop
11238 */
11239
11240 status = bm_push_buffer(pbuf, idx + 1);
11241
11242 if (status == BM_CORRUPTED) {
11243 return status;
11244 }
11245
11246 //printf("bm_check_buffers: bm_push_buffer() returned %d, loop %d, time %d\n", status, count_loops, ss_millitime() - start_time);
11247
11248 if (status != BM_MORE_EVENTS) {
11249 //DWORD t = ss_millitime() - start_time;
11250 //printf("bm_check_buffers: index %d, period %d, elapsed %d, loop %d, no more events\n", idx, start_time - last_time, t, count_loops);
11251 break;
11252 }
11253
11254 // count_loops++;
11255 }
11256
11257 // NB: this code has a logic error: if 2 buffers always have data,
11258 // this timeout will cause us to exit reading the 1st buffer
11259 // after 1000 msec, then we read the 2nd buffer exactly once,
11260 // and exit the loop because the timeout is still active -
11261 // we did not reset "start_time" when we started reading
11262 // from the 2nd buffer. Result is that we always read all
11263 // the data in a loop from the 1st buffer, but read just
11264 // one event from the 2nd buffer, resulting in severe unfairness.
11265
11266 /* stop after one second */
11267 DWORD t = ss_millitime() - start_time;
11268 if (t > 1000) {
11269 //printf("bm_check_buffers: index %d, period %d, elapsed %d, loop %d, timeout.\n", idx, start_time - last_time, t, count_loops);
11270 bMore = TRUE;
11271 break;
11272 }
11273 }
11274 }
11275
11276 //last_time = start_time;
11277
11278 return bMore;
11279
11280 }
11281#else /* LOCAL_ROUTINES */
11282
11283 return FALSE;
11284
11285#endif
11286}
#define FALSE
Definition cfortran.h:309
static INT bm_push_buffer(BUFFER *pbuf, int buffer_handle)
Definition midas.cxx:11143
#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:13051
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 9079 of file midas.cxx.

9079 {
9080
9081 BOOL is_requested = FALSE;
9082 int i;
9083 for (i = 0; i < pc->max_request_index; i++) {
9084 const EVENT_REQUEST *prequest = pc->event_request + i;
9085 if (prequest->valid) {
9086 if (bm_match_event(prequest->event_id, prequest->trigger_mask, pevent)) {
9087 /* check if this is a recent event */
9088 if (prequest->sampling_type == GET_RECENT) {
9089 if (ss_time() - pevent->time_stamp > 1) {
9090 /* skip that event */
9091 continue;
9092 }
9093 }
9094
9095 is_requested = TRUE;
9096 break;
9097 }
9098 }
9099 }
9100 return is_requested;
9101}
INT bm_match_event(short int event_id, short int trigger_mask, const EVENT_HEADER *pevent)
Definition midas.cxx:6087
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 6138 of file midas.cxx.

6138 {
6139 BUFFER_HEADER *pheader;
6140 BUFFER_CLIENT *pbclient;
6141 int j;
6142
6143 pheader = pbuf->buffer_header;
6144 pbclient = pheader->client;
6145
6146 /* now check other clients */
6147 for (j = 0; j < pheader->max_client_index; j++, pbclient++) {
6148 if (pbclient->pid) {
6149 if (!ss_pid_exists(pbclient->pid)) {
6150 cm_msg(MINFO, "bm_cleanup",
6151 "Client \'%s\' on buffer \'%s\' removed by %s because process pid %d does not exist", pbclient->name,
6152 pheader->name, who, pbclient->pid);
6153
6154 bm_remove_client_locked(pheader, j);
6155 continue;
6156 }
6157 }
6158
6159 /* If client process has no activity, clear its buffer entry. */
6160 if (pbclient->pid && pbclient->watchdog_timeout > 0) {
6161 DWORD tdiff = actual_time - pbclient->last_activity;
6162#if 0
6163 printf("buffer [%s] client [%-32s] times 0x%08x 0x%08x, diff 0x%08x %5d, timeout %d\n",
6164 pheader->name,
6165 pbclient->name,
6166 pbclient->last_activity,
6168 tdiff,
6169 tdiff,
6170 pbclient->watchdog_timeout);
6171#endif
6172 if (actual_time > pbclient->last_activity &&
6173 tdiff > pbclient->watchdog_timeout) {
6174
6175 cm_msg(MINFO, "bm_cleanup", "Client \'%s\' on buffer \'%s\' removed by %s (idle %1.1lfs, timeout %1.0lfs)",
6176 pbclient->name, pheader->name, who,
6177 tdiff / 1000.0,
6178 pbclient->watchdog_timeout / 1000.0);
6179
6180 bm_remove_client_locked(pheader, j);
6181 }
6182 }
6183 }
6184}
void bm_remove_client_locked(BUFFER_HEADER *pheader, int j)
Definition midas.cxx:6107
#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 6480 of file midas.cxx.

6480 {
6481 std::string str = msprintf("/System/buffers/%s/Clients/%s/writes_blocked_by", pbuf->buffer_name, pbuf->client_name);
6482 //printf("delete [%s]\n", str);
6483 db_delete(hDB, 0, str.c_str());
6484}
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 7317 of file midas.cxx.

7317 {
7318 if (rpc_is_remote())
7320
7321#ifdef LOCAL_ROUTINES
7322 {
7324
7325 gBuffersMutex.lock();
7326 size_t nbuf = gBuffers.size();
7327 gBuffersMutex.unlock();
7328
7329 for (size_t i = nbuf; i > 0; i--) {
7331 }
7332
7333 gBuffersMutex.lock();
7334 for (size_t i=0; i< gBuffers.size(); i++) {
7335 BUFFER* pbuf = gBuffers[i];
7336 if (!pbuf)
7337 continue;
7338 delete pbuf;
7339 pbuf = NULL;
7340 gBuffers[i] = NULL;
7341 }
7342 gBuffersMutex.unlock();
7343 }
7344#endif /* LOCAL_ROUTINES */
7345
7346 return BM_SUCCESS;
7347}
INT bm_close_buffer(INT buffer_handle)
Definition midas.cxx:7170
int cm_msg_close_buffer(void)
Definition midas.cxx:505
#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 7170 of file midas.cxx.

7170 {
7171 //printf("bm_close_buffer: handle %d\n", buffer_handle);
7172
7173 if (rpc_is_remote())
7174 return rpc_call(RPC_BM_CLOSE_BUFFER, buffer_handle);
7175
7176#ifdef LOCAL_ROUTINES
7177 {
7178 int status = 0;
7179
7180 BUFFER *pbuf = bm_get_buffer(NULL, buffer_handle, &status);
7181
7182 if (!pbuf)
7183 return status;
7184
7185 //printf("bm_close_buffer: handle %d, name [%s]\n", buffer_handle, pheader->name);
7186
7187 int i;
7188
7189 { /* delete all requests for this buffer */
7190 _request_list_mutex.lock();
7191 std::vector<EventRequest> request_list_copy = _request_list;
7192 _request_list_mutex.unlock();
7193 for (size_t i = 0; i < request_list_copy.size(); i++) {
7194 if (request_list_copy[i].buffer_handle == buffer_handle) {
7196 }
7197 }
7198 }
7199
7200 HNDLE hDB;
7202
7203 if (hDB) {
7204 /* write statistics to odb */
7206 }
7207
7208 /* lock buffer in correct order */
7209
7211
7212 if (status != BM_SUCCESS) {
7213 return status;
7214 }
7215
7217
7218 if (status != BM_SUCCESS) {
7219 pbuf->read_cache_mutex.unlock();
7220 return status;
7221 }
7222
7223 bm_lock_buffer_guard pbuf_guard(pbuf);
7224
7225 if (!pbuf_guard.is_locked()) {
7226 pbuf->write_cache_mutex.unlock();
7227 pbuf->read_cache_mutex.unlock();
7228 return pbuf_guard.get_status();
7229 }
7230
7231 BUFFER_HEADER *pheader = pbuf->buffer_header;
7232
7233 /* mark entry in _buffer as empty */
7234 pbuf->attached = false;
7235
7236 BUFFER_CLIENT* pclient = bm_get_my_client_locked(pbuf_guard);
7237
7238 if (pclient) {
7239 /* clear entry from client structure in buffer header */
7240 memset(pclient, 0, sizeof(BUFFER_CLIENT));
7241 }
7242
7243 /* calculate new max_client_index entry */
7244 for (i = MAX_CLIENTS - 1; i >= 0; i--)
7245 if (pheader->client[i].pid != 0)
7246 break;
7247 pheader->max_client_index = i + 1;
7248
7249 /* count new number of clients */
7250 int j = 0;
7251 for (i = MAX_CLIENTS - 1; i >= 0; i--)
7252 if (pheader->client[i].pid != 0)
7253 j++;
7254 pheader->num_clients = j;
7255
7256 int destroy_flag = (pheader->num_clients == 0);
7257
7258 // we hold the locks on the read cache and the write cache.
7259
7260 /* free cache */
7261 if (pbuf->read_cache_size > 0) {
7262 free(pbuf->read_cache);
7263 pbuf->read_cache = NULL;
7264 pbuf->read_cache_size = 0;
7265 pbuf->read_cache_rp = 0;
7266 pbuf->read_cache_wp = 0;
7267 }
7268
7269 if (pbuf->write_cache_size > 0) {
7270 free(pbuf->write_cache);
7271 pbuf->write_cache = NULL;
7272 pbuf->write_cache_size = 0;
7273 pbuf->write_cache_rp = 0;
7274 pbuf->write_cache_wp = 0;
7275 }
7276
7277 /* check if anyone is waiting and wake him up */
7278
7279 for (int i = 0; i < pheader->max_client_index; i++) {
7280 BUFFER_CLIENT *pclient = pheader->client + i;
7281 if (pclient->pid && (pclient->write_wait || pclient->read_wait))
7282 ss_resume(pclient->port, "B ");
7283 }
7284
7285 /* unmap shared memory, delete it if we are the last */
7286
7287 ss_shm_close(pbuf->buffer_name, pbuf->buffer_header, pbuf->shm_size, pbuf->shm_handle, destroy_flag);
7288
7289 /* after ss_shm_close() these are invalid: */
7290
7291 pheader = NULL;
7292 pbuf->buffer_header = NULL;
7293 pbuf->shm_size = 0;
7294 pbuf->shm_handle = 0;
7295
7296 /* unlock buffer in correct order */
7297
7298 pbuf_guard.unlock();
7299
7300 pbuf->write_cache_mutex.unlock();
7301 pbuf->read_cache_mutex.unlock();
7302
7303 /* delete semaphore */
7304
7305 ss_semaphore_delete(pbuf->semaphore, destroy_flag);
7306 }
7307#endif /* LOCAL_ROUTINES */
7308
7309 return BM_SUCCESS;
7310}
INT bm_delete_request(INT request_id)
Definition midas.cxx:8697
static void bm_write_buffer_statistics_to_odb(HNDLE hDB, BUFFER *pbuf, BOOL force)
Definition midas.cxx:6651
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3083
static int bm_lock_buffer_read_cache(BUFFER *pbuf)
Definition midas.cxx:8017
static int bm_lock_buffer_write_cache(BUFFER *pbuf)
Definition midas.cxx:8038
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:8394
#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 8394 of file midas.cxx.

8395{
8396 event_header->event_id = event_id;
8397 event_header->trigger_mask = trigger_mask;
8398 event_header->data_size = data_size;
8399 event_header->time_stamp = ss_time();
8400 event_header->serial_number = serial;
8401
8402 return BM_SUCCESS;
8403}
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 8405 of file midas.cxx.

8406{
8407 static std::mutex mutex;
8408
8409 event_header->event_id = event_id;
8410 event_header->trigger_mask = trigger_mask;
8411 event_header->data_size = data_size;
8412 event_header->time_stamp = ss_time();
8413 {
8414 std::lock_guard<std::mutex> lock(mutex);
8415 event_header->serial_number = *serial;
8416 *serial = *serial + 1;
8417 // implicit unlock
8418 }
8419
8420 return BM_SUCCESS;
8421}
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 9182 of file midas.cxx.

9182 {
9183 /* now convert event header */
9184 if (convert_flags) {
9185 rpc_convert_single(&pevent->event_id, TID_INT16, RPC_OUTGOING, convert_flags);
9186 rpc_convert_single(&pevent->trigger_mask, TID_INT16, RPC_OUTGOING, convert_flags);
9187 rpc_convert_single(&pevent->serial_number, TID_UINT32, RPC_OUTGOING, convert_flags);
9188 rpc_convert_single(&pevent->time_stamp, TID_UINT32, RPC_OUTGOING, convert_flags);
9189 rpc_convert_single(&pevent->data_size, TID_UINT32, RPC_OUTGOING, convert_flags);
9190 }
9191}
#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:11914
#define RPC_OUTGOING
Definition midas.h:1520
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 8697 of file midas.cxx.

8698{
8699 _request_list_mutex.lock();
8700
8701 if (request_id < 0 || size_t(request_id) >= _request_list.size()) {
8702 _request_list_mutex.unlock();
8703 return BM_INVALID_HANDLE;
8704 }
8705
8706 int buffer_handle = _request_list[request_id].buffer_handle;
8707
8708 _request_list[request_id].clear();
8709
8710 _request_list_mutex.unlock();
8711
8712 /* remove request entry from buffer */
8713 return bm_remove_event_request(buffer_handle, request_id);
8714}
INT bm_remove_event_request(INT buffer_handle, INT request_id)
Definition midas.cxx:8631
#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 8936 of file midas.cxx.

8937{
8938 _request_list_mutex.lock();
8939 bool locked = true;
8940 size_t n = _request_list.size();
8941 /* call dispatcher */
8942 for (size_t i = 0; i < n; i++) {
8943 if (!locked) {
8944 _request_list_mutex.lock();
8945 locked = true;
8946 }
8948 if (r.buffer_handle != buffer_handle)
8949 continue;
8950 if (!bm_match_event(r.event_id, r.trigger_mask, pevent))
8951 continue;
8952 /* must release the lock on the request list: user provided r.dispatcher() can add or remove event requests, and we will deadlock. K.O. */
8953 _request_list_mutex.unlock();
8954 locked = false;
8955 /* if event is fragmented, call defragmenter */
8956 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))) {
8957 bm_defragment_event(buffer_handle, i, pevent, (void *) (pevent + 1), r.dispatcher);
8958 } else {
8959 r.dispatcher(buffer_handle, i, pevent, (void *) (pevent + 1));
8960 }
8961 }
8962 if (locked)
8963 _request_list_mutex.unlock();
8964}
static void bm_defragment_event(HNDLE buffer_handle, HNDLE request_id, EVENT_HEADER *pevent, void *pdata, EVENT_HANDLER *dispatcher)
Definition midas.cxx:11525
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 11481 of file midas.cxx.

11481 {
11482 if (rpc_is_remote())
11484
11485#ifdef LOCAL_ROUTINES
11486 {
11487 std::vector<BUFFER*> mybuffers;
11488
11489 gBuffersMutex.lock();
11490 mybuffers = gBuffers;
11491 gBuffersMutex.unlock();
11492
11493 /* go through all buffers */
11494 for (BUFFER* pbuf : mybuffers) {
11495 if (!pbuf)
11496 continue;
11497 if (!pbuf->attached)
11498 continue;
11499
11500 int status = bm_skip_event(pbuf);
11501 if (status != BM_SUCCESS)
11502 return status;
11503 }
11504 }
11505#endif /* LOCAL_ROUTINES */
11506
11507 return BM_SUCCESS;
11508}
static int bm_skip_event(BUFFER *pbuf)
Definition midas.cxx:11074
#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 9105 of file midas.cxx.

9106{
9107 BUFFER* pbuf = pbuf_guard.get_pbuf();
9108 BUFFER_HEADER* pheader = pbuf->buffer_header;
9109 BUFFER_CLIENT *pc = bm_get_my_client_locked(pbuf_guard);
9110 BOOL need_wakeup = FALSE;
9111
9112 //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);
9113
9114 /* loop over all events in the buffer */
9115
9116 while (1) {
9117 EVENT_HEADER *pevent = NULL;
9118 int event_size = 3; // poison value
9119 int total_size = 3; // poison value
9120
9121 int status = bm_peek_buffer_locked(pbuf, pheader, pc, &pevent, &event_size, &total_size);
9122 if (status == BM_CORRUPTED) {
9123 return status;
9124 } else if (status != BM_SUCCESS) {
9125 /* event buffer is empty */
9126 if (timeout_msec == BM_NO_WAIT) {
9127 if (need_wakeup)
9128 bm_wakeup_producers_locked(pheader, pc);
9129 if (pbuf->read_cache_rp == pbuf->read_cache_wp) {
9130 // read cache is empty
9131 return BM_ASYNC_RETURN;
9132 }
9133 return BM_SUCCESS;
9134 }
9135
9136 int status = bm_wait_for_more_events_locked(pbuf_guard, pc, timeout_msec, TRUE);
9137
9138 if (status != BM_SUCCESS) {
9139 // we only come here with SS_ABORT & co
9140 return status;
9141 }
9142
9143 // make sure we wait for new event only once
9144 timeout_msec = BM_NO_WAIT;
9145 // go back to bm_peek_buffer_locked
9146 continue;
9147 }
9148
9149 /* loop over all requests: if this event matches a request,
9150 * copy it to the read cache */
9151
9152 BOOL is_requested = bm_check_requests(pc, pevent);
9153
9154 if (is_requested) {
9155 if (pbuf->read_cache_wp + total_size > pbuf->read_cache_size) {
9156 /* read cache is full */
9157 if (need_wakeup)
9158 bm_wakeup_producers_locked(pheader, pc);
9159 return BM_SUCCESS;
9160 }
9161
9163
9164 pbuf->read_cache_wp += total_size;
9165
9166 /* update statistics */
9167 pheader->num_out_events++;
9168 pbuf->count_read++;
9169 pbuf->bytes_read += event_size;
9170 }
9171
9172 /* shift read pointer */
9173
9174 int new_read_pointer = bm_incr_rp_no_check(pheader, pc->read_pointer, total_size);
9175 pc->read_pointer = new_read_pointer;
9176
9177 need_wakeup = TRUE;
9178 }
9179 /* NOT REACHED */
9180}
BUFFER * get_pbuf() const
Definition midas.cxx:3253
static void bm_wakeup_producers_locked(const BUFFER_HEADER *pheader, const BUFFER_CLIENT *pc)
Definition midas.cxx:8900
static int bm_incr_rp_no_check(const BUFFER_HEADER *pheader, int rp, int total_size)
Definition midas.cxx:6295
static BOOL bm_check_requests(const BUFFER_CLIENT *pc, const EVENT_HEADER *pevent)
Definition midas.cxx:9079
static void bm_read_from_buffer_locked(const BUFFER_HEADER *pheader, int rp, char *buf, int event_size)
Definition midas.cxx:9049
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:9004
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:9505
#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 9702 of file midas.cxx.

9702 {
9703 if (pc->pid) {
9704 int j;
9705 for (j = 0; j < pc->max_request_index; j++) {
9706 const EVENT_REQUEST *prequest = pc->event_request + j;
9707 if (prequest->valid && bm_match_event(prequest->event_id, prequest->trigger_mask, pevent)) {
9708 return prequest->id;
9709 }
9710 }
9711 }
9712
9713 return -1;
9714}
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 10335 of file midas.cxx.

10336{
10337 if (rpc_is_remote()) {
10338 return bm_flush_cache_rpc(buffer_handle, timeout_msec);
10339 }
10340
10341#ifdef LOCAL_ROUTINES
10342 {
10343 INT status = 0;
10344
10345 //printf("bm_flush_cache!\n");
10346
10347 BUFFER *pbuf = bm_get_buffer("bm_flush_cache", buffer_handle, &status);
10348
10349 if (!pbuf)
10350 return status;
10351
10352 if (pbuf->write_cache_size == 0)
10353 return BM_SUCCESS;
10354
10356
10357 if (status != BM_SUCCESS)
10358 return status;
10359
10360 /* check if anything needs to be flushed */
10361 if (pbuf->write_cache_wp == 0) {
10362 pbuf->write_cache_mutex.unlock();
10363 return BM_SUCCESS;
10364 }
10365
10366 /* lock the buffer */
10367 bm_lock_buffer_guard pbuf_guard(pbuf);
10368
10369 if (!pbuf_guard.is_locked())
10370 return pbuf_guard.get_status();
10371
10372 status = bm_flush_cache_locked(pbuf_guard, timeout_msec);
10373
10374 /* unlock in correct order */
10375
10376 if (pbuf_guard.is_locked()) {
10377 // check if bm_wait_for_free_space() failed to relock the buffer
10378 pbuf_guard.unlock();
10379 }
10380
10381 pbuf->write_cache_mutex.unlock();
10382
10383 return status;
10384 }
10385#endif /* LOCAL_ROUTINES */
10386
10387 return BM_SUCCESS;
10388}
static int bm_flush_cache_rpc(int buffer_handle, int timeout_msec)
Definition midas.cxx:10100
static INT bm_flush_cache_locked(bm_lock_buffer_guard &pbuf_guard, int timeout_msec)
Definition midas.cxx:10191
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 10191 of file midas.cxx.

10192{
10193 // NB we come here with write cache locked and buffer locked.
10194
10195 {
10196 INT status = 0;
10197
10198 //printf("bm_flush_cache_locked!\n");
10199
10200 BUFFER* pbuf = pbuf_guard.get_pbuf();
10201 BUFFER_HEADER* pheader = pbuf->buffer_header;
10202
10203 //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);
10204
10205 int old_write_pointer = pheader->write_pointer;
10206
10207 int request_id[MAX_CLIENTS];
10208 for (int i = 0; i < pheader->max_client_index; i++) {
10209 request_id[i] = -1;
10210 }
10211
10212 size_t ask_rp = pbuf->write_cache_rp;
10213 size_t ask_wp = pbuf->write_cache_wp;
10214
10215 if (ask_wp == 0) { // nothing to do
10216 return BM_SUCCESS;
10217 }
10218
10219 if (ask_rp == ask_wp) { // nothing to do
10220 return BM_SUCCESS;
10221 }
10222
10223 assert(ask_rp < ask_wp);
10224
10225 size_t ask_free = ALIGN8(ask_wp - ask_rp);
10226
10227 if (ask_free == 0) { // nothing to do
10228 return BM_SUCCESS;
10229 }
10230
10231#if 0
10233 if (status != BM_SUCCESS) {
10234 printf("bm_flush_cache: corrupted 111!\n");
10235 abort();
10236 }
10237#endif
10238
10239 status = bm_wait_for_free_space_locked(pbuf_guard, timeout_msec, ask_free, true);
10240
10241 if (status != BM_SUCCESS) {
10242 return status;
10243 }
10244
10245 // NB: ask_rp, ask_wp and ask_free are invalid after calling bm_wait_for_free_space():
10246 //
10247 // wait_for_free_space() will sleep with all locks released,
10248 // during this time, another thread may call bm_send_event() that will
10249 // add one or more events to the write cache and after wait_for_free_space()
10250 // returns, size of data in cache will be bigger than the amount
10251 // of free space we requested. so we need to keep track of how
10252 // much data we write to the buffer and ask for more data
10253 // if we run short. This is the reason for the big loop
10254 // around wait_for_free_space(). We ask for slightly too little free
10255 // space to make sure all this code is always used and does work. K.O.
10256
10257 if (pbuf->write_cache_wp == 0) {
10258 /* somebody emptied the cache while we were inside bm_wait_for_free_space */
10259 return BM_SUCCESS;
10260 }
10261
10262 //size_t written = 0;
10263 while (pbuf->write_cache_rp < pbuf->write_cache_wp) {
10264 /* loop over all events in cache */
10265
10266 const EVENT_HEADER *pevent = (const EVENT_HEADER *) (pbuf->write_cache + pbuf->write_cache_rp);
10267 size_t event_size = (pevent->data_size + sizeof(EVENT_HEADER));
10268 size_t total_size = ALIGN8(event_size);
10269
10270#if 0
10271 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",
10272 int(pbuf->write_cache_size),
10273 int(pbuf->write_cache_wp),
10274 int(pbuf->write_cache_rp),
10275 int(pevent->data_size),
10276 int(event_size),
10277 int(total_size),
10278 int(ask_free),
10279 int(written));
10280#endif
10281
10282 // check for crazy event size
10283 assert(total_size >= sizeof(EVENT_HEADER));
10284 assert(total_size <= (size_t)pheader->size);
10285
10286 bm_write_to_buffer_locked(pheader, 1, (char**)&pevent, &event_size, total_size);
10287
10288 /* update statistics */
10289 pheader->num_in_events++;
10290 pbuf->count_sent += 1;
10291 pbuf->bytes_sent += total_size;
10292
10293 /* see comment for the same code in bm_send_event().
10294 * We make sure the buffer is never 100% full */
10295 assert(pheader->write_pointer != pheader->read_pointer);
10296
10297 /* check if anybody has a request for this event */
10298 for (int i = 0; i < pheader->max_client_index; i++) {
10299 BUFFER_CLIENT *pc = pheader->client + i;
10300 int r = bm_find_first_request_locked(pc, pevent);
10301 if (r >= 0) {
10302 request_id[i] = r;
10303 }
10304 }
10305
10306 /* this loop does not loop forever because rp
10307 * is monotonously incremented here. write_cache_wp does
10308 * not change */
10309
10310 pbuf->write_cache_rp += total_size;
10311 //written += total_size;
10312
10313 assert(pbuf->write_cache_rp > 0);
10314 assert(pbuf->write_cache_rp <= pbuf->write_cache_size);
10315 assert(pbuf->write_cache_rp <= pbuf->write_cache_wp);
10316 }
10317
10318 /* the write cache is now empty */
10319 assert(pbuf->write_cache_wp == pbuf->write_cache_rp);
10320 pbuf->write_cache_wp = 0;
10321 pbuf->write_cache_rp = 0;
10322
10323 /* check which clients are waiting */
10324 for (int i = 0; i < pheader->max_client_index; i++) {
10325 BUFFER_CLIENT *pc = pheader->client + i;
10326 bm_notify_reader_locked(pheader, pc, old_write_pointer, request_id[i]);
10327 }
10328 }
10329
10330 return BM_SUCCESS;
10331}
static void bm_notify_reader_locked(BUFFER_HEADER *pheader, BUFFER_CLIENT *pc, int old_write_pointer, int request_id)
Definition midas.cxx:9716
static int bm_find_first_request_locked(BUFFER_CLIENT *pc, const EVENT_HEADER *pevent)
Definition midas.cxx:9702
static int bm_validate_buffer_locked(const BUFFER *pbuf)
Definition midas.cxx:6379
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:9617
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:9193
#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 10100 of file midas.cxx.

10101{
10102 //printf("bm_flush_cache_rpc: handle %d, timeout %d\n", buffer_handle, timeout_msec);
10103
10104 DWORD time_start = ss_millitime();
10105 DWORD time_end = time_start + timeout_msec;
10106 DWORD time_bombout = time_end;
10107
10108 if (timeout_msec < 10000)
10109 time_bombout = time_start + 10000; // 10 seconds
10110
10111 int xtimeout_msec = timeout_msec;
10112
10113 while (1) {
10114 if (timeout_msec == BM_WAIT) {
10115 xtimeout_msec = 1000;
10116 } else if (timeout_msec == BM_NO_WAIT) {
10117 xtimeout_msec = BM_NO_WAIT;
10118 } else {
10119 if (xtimeout_msec > 1000) {
10120 xtimeout_msec = 1000;
10121 }
10122 }
10123
10124 int status = rpc_call(RPC_BM_FLUSH_CACHE, buffer_handle, xtimeout_msec);
10125
10126 //printf("bm_flush_cache_rpc: handle %d, timeout %d, status %d\n", buffer_handle, xtimeout_msec, status);
10127
10128 if (status == BM_ASYNC_RETURN) {
10129 if (timeout_msec == BM_WAIT) {
10130 DWORD now = ss_millitime();
10131 if (now >= time_bombout) {
10132 // timeout
10133 return BM_TIMEOUT;
10134 }
10135
10136 // BM_WAIT means wait forever
10137 continue;
10138 } else if (timeout_msec == BM_NO_WAIT) {
10139 // BM_NO_WAIT means do not wait
10140 return status;
10141 } else {
10142 DWORD now = ss_millitime();
10143 if (now >= time_end) {
10144 // timeout, return BM_ASYNC_RETURN
10145 return status;
10146 }
10147
10148 DWORD remain = time_end - now;
10149
10150 if (remain < (DWORD)xtimeout_msec) {
10151 xtimeout_msec = remain;
10152 }
10153
10154 if (now >= time_bombout) {
10155 // timeout
10156 return BM_TIMEOUT;
10157 }
10158
10159 // keep asking for event...
10160 continue;
10161 }
10162 } else if (status == BM_SUCCESS) {
10163 // success, return BM_SUCCESS
10164 return status;
10165 } else {
10166 // error
10167 return status;
10168 }
10169 }
10170}
#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 7149 of file midas.cxx.

7150{
7151 gBuffersMutex.lock();
7152 for (size_t i = 0; i < gBuffers.size(); i++) {
7153 BUFFER* pbuf = gBuffers[i];
7154 if (pbuf && pbuf->attached && equal_ustring(pbuf->buffer_name, buffer_name)) {
7155 *buffer_handle = i + 1;
7156 gBuffersMutex.unlock();
7157 return BM_SUCCESS;
7158 }
7159 }
7160 gBuffersMutex.unlock();
7161 return BM_NOT_FOUND;
7162}
#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 8968 of file midas.cxx.

8968 {
8969 /* increment read cache read pointer */
8970 pbuf->read_cache_rp += total_size;
8971
8972 if (pbuf->read_cache_rp == pbuf->read_cache_wp) {
8973 pbuf->read_cache_rp = 0;
8974 pbuf->read_cache_wp = 0;
8975 }
8976}
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 6295 of file midas.cxx.

6296{
6297#if 0
6298 if (gRpLog == NULL) {
6299 gRpLog = fopen("rp.log", "a");
6300 }
6301 if (gRpLog && (total_size < 16)) {
6302 const char *pdata = (const char *) (pheader + 1);
6303 const DWORD *pevent = (const DWORD*) (pdata + rp);
6304 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,
6305 pevent[0], pevent[1], pevent[2], pevent[3], pevent[4], pevent[5]);
6306 }
6307#endif
6308
6309 // these checks are already done before we come here.
6310 // but we check again as last-ressort protection. K.O.
6311 assert(total_size > 0);
6312 assert(total_size >= (int)sizeof(EVENT_HEADER));
6313
6314 rp += total_size;
6315 if (rp >= pheader->size) {
6316 rp -= pheader->size;
6317 } else if ((rp + (int) sizeof(EVENT_HEADER)) > pheader->size) {
6318 // note: ">" here to match bm_write_to_buffer_locked() and bm_validate_rp().
6319 // if at the end of the buffer, the remaining free space is exactly
6320 // equal to the size of an event header, the event header
6321 // is written there, the pointer is wrapped and the event data
6322 // is written to the beginning of the buffer.
6323 rp = 0;
6324 }
6325 return rp;
6326}
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 6087 of file midas.cxx.

6087 {
6088 // NB: cast everything to unsigned 16 bit to avoid bitwise comparison failure
6089 // because of mismatch in sign-extension between signed 16-bit event_id and
6090 // unsigned 16-bit constants. K.O.
6091
6092 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)))
6093 /* fragmented event */
6094 return (((uint16_t(event_id) == uint16_t(EVENTID_ALL)) || (uint16_t(event_id) == (uint16_t(pevent->event_id) & uint16_t(0x0FFF))))
6095 && ((uint16_t(trigger_mask) == uint16_t(TRIGGER_ALL)) || ((uint16_t(trigger_mask) & uint16_t(pevent->trigger_mask)))));
6096
6097 return (((uint16_t(event_id) == uint16_t(EVENTID_ALL)) || (uint16_t(event_id) == uint16_t(pevent->event_id)))
6098 && ((uint16_t(trigger_mask) == uint16_t(TRIGGER_ALL)) || ((uint16_t(trigger_mask) & uint16_t(pevent->trigger_mask)))));
6099}
#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 6328 of file midas.cxx.

6328 {
6329 const EVENT_HEADER *pevent = (const EVENT_HEADER *) (pdata + rp);
6330 int event_size = pevent->data_size + sizeof(EVENT_HEADER);
6331 int total_size = ALIGN8(event_size);
6332
6333 if (pevent->data_size <= 0 || total_size <= 0 || total_size > pheader->size) {
6334 cm_msg(MERROR, "bm_next_rp",
6335 "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",
6336 pheader->name,
6337 rp,
6338 pevent->data_size,
6339 event_size,
6340 total_size,
6341 pheader->read_pointer,
6342 pheader->write_pointer,
6343 pheader->size,
6344 who);
6345 return -1;
6346 }
6347
6348 int remaining = 0;
6349 if (rp < pheader->write_pointer) {
6350 remaining = pheader->write_pointer - rp;
6351 } else {
6352 remaining = pheader->size - rp;
6353 remaining += pheader->write_pointer;
6354 }
6355
6356 //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);
6357
6358 if (total_size > remaining) {
6359 cm_msg(MERROR, "bm_next_rp",
6360 "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",
6361 pheader->name,
6362 rp,
6363 pevent->data_size,
6364 event_size,
6365 total_size,
6366 pheader->read_pointer,
6367 pheader->write_pointer,
6368 pheader->size,
6369 remaining,
6370 who);
6371 return -1;
6372 }
6373
6374 rp = bm_incr_rp_no_check(pheader, rp, total_size);
6375
6376 return rp;
6377}
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 9716 of file midas.cxx.

9716 {
9717 if (request_id >= 0) {
9718 /* if that client has a request and is suspended, wake it up */
9719 if (pc->read_wait) {
9720 char str[80];
9721 sprintf(str, "B %s %d", pheader->name, request_id);
9722 ss_resume(pc->port, str);
9723 //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);
9724 //printf("bm_notify_reader_locked: buffer [%s] client [%s] clear read_wait!\n", pheader->name, pc->name);
9725 pc->read_wait = FALSE;
9726 }
9727 }
9728}
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:6782
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:8578
INT cm_yield(INT millisec)
Definition midas.cxx:5716
INT cm_connect_experiment(const char *host_name, const char *exp_name, const char *client_name, void(*func)(char *))
Definition midas.cxx:2352
INT cm_disconnect_experiment(void)
Definition midas.cxx:2918
#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 6782 of file midas.cxx.

6782 {
6783 INT status;
6784
6785 if (rpc_is_remote()) {
6786 status = rpc_call(RPC_BM_OPEN_BUFFER, buffer_name, buffer_size, buffer_handle);
6787
6788 HNDLE hDB;
6790 if (status != SUCCESS || hDB == 0) {
6791 cm_msg(MERROR, "bm_open_buffer", "cannot open buffer \'%s\' - not connected to ODB", buffer_name);
6792 return BM_NO_SHM;
6793 }
6794
6796
6797 int size = sizeof(INT);
6798 status = db_get_value(hDB, 0, "/Experiment/MAX_EVENT_SIZE", &_bm_max_event_size, &size, TID_UINT32, TRUE);
6799
6800 if (status != DB_SUCCESS) {
6801 cm_msg(MERROR, "bm_open_buffer", "Cannot get ODB /Experiment/MAX_EVENT_SIZE, db_get_value() status %d",
6802 status);
6803 return status;
6804 }
6805
6806 return status;
6807 }
6808#ifdef LOCAL_ROUTINES
6809 {
6810 HNDLE shm_handle;
6811 size_t shm_size;
6812 HNDLE hDB;
6813 const int max_buffer_size = 2 * 1000 * 1024 * 1024; // limited by 32-bit integers in the buffer header
6814
6815 bm_cleanup("bm_open_buffer", ss_millitime(), FALSE);
6816
6817 if (!buffer_name || !buffer_name[0]) {
6818 cm_msg(MERROR, "bm_open_buffer", "cannot open buffer with zero name");
6819 return BM_INVALID_PARAM;
6820 }
6821
6822 if (strlen(buffer_name) >= NAME_LENGTH) {
6823 cm_msg(MERROR, "bm_open_buffer", "buffer name \"%s\" is longer than %d bytes", buffer_name, NAME_LENGTH);
6824 return BM_INVALID_PARAM;
6825 }
6826
6828
6829 if (status != SUCCESS || hDB == 0) {
6830 //cm_msg(MERROR, "bm_open_buffer", "cannot open buffer \'%s\' - not connected to ODB", buffer_name);
6831 return BM_NO_SHM;
6832 }
6833
6834 /* get buffer size from ODB, user parameter as default if not present in ODB */
6835 std::string odb_path;
6836 odb_path += "/Experiment/Buffer sizes/";
6837 odb_path += buffer_name;
6838
6839 int size = sizeof(INT);
6840 status = db_get_value(hDB, 0, odb_path.c_str(), &buffer_size, &size, TID_UINT32, TRUE);
6841
6842 if (buffer_size <= 0 || buffer_size > max_buffer_size) {
6843 cm_msg(MERROR, "bm_open_buffer",
6844 "Cannot open buffer \"%s\", invalid buffer size %d in ODB \"%s\", maximum buffer size is %d",
6845 buffer_name, buffer_size, odb_path.c_str(), max_buffer_size);
6846
6847 // 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
6848
6849 if (strcmp(buffer_name, MESSAGE_BUFFER_NAME) != 0)
6850 return BM_INVALID_PARAM;
6851
6852 cm_msg(MERROR, "bm_open_buffer",
6853 "Will use default SYSMSG buffer size %d to open buffer \"%s\"",
6855 buffer_size = MESSAGE_BUFFER_SIZE;
6856 }
6857
6859
6860 size = sizeof(INT);
6861 status = db_get_value(hDB, 0, "/Experiment/MAX_EVENT_SIZE", &_bm_max_event_size, &size, TID_UINT32, TRUE);
6862
6863 if (status != DB_SUCCESS) {
6864 cm_msg(MERROR, "bm_open_buffer", "Cannot get ODB /Experiment/MAX_EVENT_SIZE, db_get_value() status %d",
6865 status);
6866 return status;
6867 }
6868
6869 /* check if buffer already is open */
6870 gBuffersMutex.lock();
6871 for (size_t i = 0; i < gBuffers.size(); i++) {
6872 BUFFER* pbuf = gBuffers[i];
6873 if (pbuf && pbuf->attached && equal_ustring(pbuf->buffer_name, buffer_name)) {
6874 *buffer_handle = i + 1;
6875 gBuffersMutex.unlock();
6876 return BM_SUCCESS;
6877 }
6878 }
6879 gBuffersMutex.unlock();
6880
6881 // only one thread at a time should create new buffers
6882
6883 static std::mutex gNewBufferMutex;
6884 std::lock_guard<std::mutex> guard(gNewBufferMutex);
6885
6886 // if we had a race against another thread
6887 // and while we were waiting for gNewBufferMutex
6888 // the other thread created this buffer, we return it.
6889
6890 gBuffersMutex.lock();
6891 for (size_t i = 0; i < gBuffers.size(); i++) {
6892 BUFFER* pbuf = gBuffers[i];
6893 if (pbuf && pbuf->attached && equal_ustring(pbuf->buffer_name, buffer_name)) {
6894 *buffer_handle = i + 1;
6895 gBuffersMutex.unlock();
6896 return BM_SUCCESS;
6897 }
6898 }
6899 gBuffersMutex.unlock();
6900
6901 /* allocate new BUFFER object */
6902
6903 BUFFER* pbuf = new BUFFER;
6904
6905 /* there is no constructor for BUFFER object, we have to zero the arrays manually */
6906
6907 for (int i=0; i<MAX_CLIENTS; i++) {
6908 pbuf->client_count_write_wait[i] = 0;
6909 pbuf->client_time_write_wait[i] = 0;
6910 }
6911
6912 /* create buffer semaphore */
6913
6915
6916 if (status != SS_CREATED && status != SS_SUCCESS) {
6917 *buffer_handle = 0;
6918 delete pbuf;
6919 return BM_NO_SEMAPHORE;
6920 }
6921
6922 std::string client_name = cm_get_client_name();
6923
6924 /* store client name */
6925 mstrlcpy(pbuf->client_name, client_name.c_str(), sizeof(pbuf->client_name));
6926
6927 /* store buffer name */
6928 mstrlcpy(pbuf->buffer_name, buffer_name, sizeof(pbuf->buffer_name));
6929
6930 /* lock buffer semaphore to avoid race with bm_open_buffer() in a different program */
6931
6932 pbuf->attached = true; // required by bm_lock_buffer()
6933
6934 bm_lock_buffer_guard pbuf_guard(pbuf);
6935
6936 if (!pbuf_guard.is_locked()) {
6937 // cannot happen, no other thread can see this pbuf
6938 abort();
6939 return BM_NO_SEMAPHORE;
6940 }
6941
6942 /* open shared memory */
6943
6944 void *p = NULL;
6945 status = ss_shm_open(buffer_name, sizeof(BUFFER_HEADER) + buffer_size, &p, &shm_size, &shm_handle, FALSE);
6946
6947 if (status != SS_SUCCESS && status != SS_CREATED) {
6948 *buffer_handle = 0;
6949 pbuf_guard.unlock();
6950 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
6951 delete pbuf;
6952 return BM_NO_SHM;
6953 }
6954
6955 pbuf->buffer_header = (BUFFER_HEADER *) p;
6956
6957 BUFFER_HEADER *pheader = pbuf->buffer_header;
6958
6959 bool shm_created = (status == SS_CREATED);
6960
6961 if (shm_created) {
6962 /* initialize newly created shared memory */
6963
6964 memset(pheader, 0, sizeof(BUFFER_HEADER) + buffer_size);
6965
6966 mstrlcpy(pheader->name, buffer_name, sizeof(pheader->name));
6967 pheader->size = buffer_size;
6968
6969 } else {
6970 /* validate existing shared memory */
6971
6972 if (!equal_ustring(pheader->name, buffer_name)) {
6973 // unlock before calling cm_msg(). if we are SYSMSG, we wil ldeadlock. K.O.
6974 pbuf_guard.unlock();
6975 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
6976 cm_msg(MERROR, "bm_open_buffer",
6977 "Buffer \"%s\" is corrupted, mismatch of buffer name in shared memory \"%s\"", buffer_name,
6978 pheader->name);
6979 *buffer_handle = 0;
6980 delete pbuf;
6981 return BM_CORRUPTED;
6982 }
6983
6984 if ((pheader->num_clients < 0) || (pheader->num_clients > MAX_CLIENTS)) {
6985 // unlock before calling cm_msg(). if we are SYSMSG, we wil ldeadlock. K.O.
6986 pbuf_guard.unlock();
6987 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
6988 cm_msg(MERROR, "bm_open_buffer", "Buffer \"%s\" is corrupted, num_clients %d exceeds MAX_CLIENTS %d",
6990 *buffer_handle = 0;
6991 delete pbuf;
6992 return BM_CORRUPTED;
6993 }
6994
6995 if ((pheader->max_client_index < 0) || (pheader->max_client_index > MAX_CLIENTS)) {
6996 // unlock before calling cm_msg(). if we are SYSMSG, we wil ldeadlock. K.O.
6997 pbuf_guard.unlock();
6998 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
6999 cm_msg(MERROR, "bm_open_buffer", "Buffer \"%s\" is corrupted, max_client_index %d exceeds MAX_CLIENTS %d",
7001 *buffer_handle = 0;
7002 delete pbuf;
7003 return BM_CORRUPTED;
7004 }
7005
7006 /* check if buffer size is identical */
7007 if (pheader->size != buffer_size) {
7008 cm_msg(MINFO, "bm_open_buffer", "Buffer \"%s\" requested size %d differs from existing size %d",
7009 buffer_name, buffer_size, pheader->size);
7010
7011 buffer_size = pheader->size;
7012
7013 ss_shm_close(buffer_name, p, shm_size, shm_handle, FALSE);
7014
7015 status = ss_shm_open(buffer_name, sizeof(BUFFER_HEADER) + buffer_size, &p, &shm_size, &shm_handle, FALSE);
7016
7017 if (status != SS_SUCCESS) {
7018 *buffer_handle = 0;
7019 pbuf_guard.unlock();
7020 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
7021 delete pbuf;
7022 return BM_NO_SHM;
7023 }
7024
7025 pbuf->buffer_header = (BUFFER_HEADER *) p;
7026 pheader = pbuf->buffer_header;
7027 }
7028 }
7029
7030 /* shared memory is good from here down */
7031
7032 pbuf->attached = true;
7033
7034 pbuf->shm_handle = shm_handle;
7035 pbuf->shm_size = shm_size;
7036 pbuf->callback = FALSE;
7037
7038 bm_cleanup_buffer_locked(pbuf, "bm_open_buffer", ss_millitime());
7039
7041 if (status != BM_SUCCESS) {
7042 cm_msg(MERROR, "bm_open_buffer",
7043 "buffer \'%s\' is corrupted, bm_validate_buffer() status %d, calling bm_reset_buffer()...", buffer_name,
7044 status);
7046 cm_msg(MINFO, "bm_open_buffer", "buffer \'%s\' was reset, all buffered events were lost", buffer_name);
7047 }
7048
7049 /* add our client BUFFER_HEADER */
7050
7051 int iclient = 0;
7052 for (; iclient < MAX_CLIENTS; iclient++)
7053 if (pheader->client[iclient].pid == 0)
7054 break;
7055
7056 if (iclient == MAX_CLIENTS) {
7057 *buffer_handle = 0;
7058 // unlock before calling cm_msg(). if we are SYSMSG, we wil ldeadlock. K.O.
7059 pbuf_guard.unlock();
7060 pbuf_guard.invalidate(); // destructor will see a deleted pbuf
7061 delete pbuf;
7062 cm_msg(MERROR, "bm_open_buffer", "buffer \'%s\' maximum number of clients %d exceeded", buffer_name, MAX_CLIENTS);
7063 return BM_NO_SLOT;
7064 }
7065
7066 /* store slot index in _buffer structure */
7067 pbuf->client_index = iclient;
7068
7069 /*
7070 Save the index of the last client of that buffer so that later only
7071 the clients 0..max_client_index-1 have to be searched through.
7072 */
7073 pheader->num_clients++;
7074 if (iclient + 1 > pheader->max_client_index)
7075 pheader->max_client_index = iclient + 1;
7076
7077 /* setup buffer header and client structure */
7078 BUFFER_CLIENT *pclient = &pheader->client[iclient];
7079
7080 memset(pclient, 0, sizeof(BUFFER_CLIENT));
7081
7082 mstrlcpy(pclient->name, client_name.c_str(), sizeof(pclient->name));
7083
7084 pclient->pid = ss_getpid();
7085
7087
7088 pclient->read_pointer = pheader->write_pointer;
7089 pclient->last_activity = ss_millitime();
7090
7092
7093 pbuf_guard.unlock();
7094
7095 /* shared memory is not locked from here down, do not touch pheader and pbuf->buffer_header! */
7096
7097 pheader = NULL;
7098
7099 /* we are not holding any locks from here down, but other threads cannot see this pbuf yet */
7100
7103
7104 /* add pbuf to buffer list */
7105
7106 gBuffersMutex.lock();
7107
7108 bool added = false;
7109 for (size_t i=0; i<gBuffers.size(); i++) {
7110 if (gBuffers[i] == NULL) {
7111 gBuffers[i] = pbuf;
7112 added = true;
7113 *buffer_handle = i+1;
7114 break;
7115 }
7116 }
7117 if (!added) {
7118 *buffer_handle = gBuffers.size() + 1;
7119 gBuffers.push_back(pbuf);
7120 }
7121
7122 /* from here down we should not touch pbuf without locking it */
7123
7124 pbuf = NULL;
7125
7126 gBuffersMutex.unlock();
7127
7128 /* new buffer is now ready for use */
7129
7130 /* initialize buffer counters */
7131 bm_init_buffer_counters(*buffer_handle);
7132
7133 bm_cleanup("bm_open_buffer", ss_millitime(), FALSE);
7134
7135 if (shm_created)
7136 return BM_CREATED;
7137 }
7138#endif /* LOCAL_ROUTINES */
7139
7140 return BM_SUCCESS;
7141}
static void bm_cleanup_buffer_locked(BUFFER *pbuf, const char *who, DWORD actual_time)
Definition midas.cxx:6138
static DWORD _bm_max_event_size
Definition midas.cxx:5986
static void bm_clear_buffer_statistics(HNDLE hDB, BUFFER *pbuf)
Definition midas.cxx:6480
static void bm_reset_buffer_locked(BUFFER *pbuf)
Definition midas.cxx:6463
INT cm_get_watchdog_params(BOOL *call_watchdog, DWORD *timeout)
Definition midas.cxx:3397
std::string cm_get_client_name()
Definition midas.cxx:2133
static void bm_cleanup(const char *who, DWORD actual_time, BOOL wrong_interval)
Definition midas.cxx:6224
#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:8176
#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 9004 of file midas.cxx.

9005{
9006 if (pc->read_pointer == pheader->write_pointer) {
9007 /* no more events buffered for this client */
9008 if (!pc->read_wait) {
9009 //printf("bm_peek_buffer_locked: buffer [%s] client [%s], set read_wait!\n", pheader->name, pc->name);
9010 pc->read_wait = TRUE;
9011 }
9012 return BM_ASYNC_RETURN;
9013 }
9014
9015 if (pc->read_wait) {
9016 //printf("bm_peek_buffer_locked: buffer [%s] client [%s], clear read_wait!\n", pheader->name, pc->name);
9017 pc->read_wait = FALSE;
9018 }
9019
9020 if ((pc->read_pointer < 0) || (pc->read_pointer >= pheader->size)) {
9021 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);
9022 return BM_CORRUPTED;
9023 }
9024
9025 char *pdata = (char *) (pheader + 1);
9026
9027 EVENT_HEADER *pevent = (EVENT_HEADER *) (pdata + pc->read_pointer);
9028 int event_size = pevent->data_size + sizeof(EVENT_HEADER);
9029 int total_size = ALIGN8(event_size);
9030
9031 if ((total_size <= 0) || (total_size > pheader->size)) {
9032 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);
9033 return BM_CORRUPTED;
9034 }
9035
9036 assert(total_size > 0);
9037 assert(total_size <= pheader->size);
9038
9039 if (ppevent)
9040 *ppevent = pevent;
9041 if (pevent_size)
9042 *pevent_size = event_size;
9043 if (ptotal_size)
9044 *ptotal_size = total_size;
9045
9046 return BM_SUCCESS;
9047}
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 8978 of file midas.cxx.

8979{
8980 if (pbuf->read_cache_rp == pbuf->read_cache_wp)
8981 return FALSE;
8982
8983 EVENT_HEADER *pevent = (EVENT_HEADER *) (pbuf->read_cache + pbuf->read_cache_rp);
8984 int event_size = pevent->data_size + sizeof(EVENT_HEADER);
8985 int total_size = ALIGN8(event_size);
8986
8987 if (ppevent)
8988 *ppevent = pevent;
8989 if (pevent_size)
8990 *pevent_size = event_size;
8991 if (ptotal_size)
8992 *ptotal_size = total_size;
8993
8994 return TRUE;
8995}
Here is the caller graph for this function:

◆ bm_poll_event()

INT bm_poll_event ( void  )

Definition at line 11367 of file midas.cxx.

11381{
11382 BOOL dispatched_something = FALSE;
11383
11384 //printf("bm_poll_event!\n");
11385
11386 DWORD start_time = ss_millitime();
11387
11388 std::vector<char> vec;
11389
11390 /* loop over all requests */
11391 _request_list_mutex.lock();
11392 bool locked = true;
11393 size_t n = _request_list.size();
11394 for (size_t i = 0; i < n; i++) {
11395 if (!locked) {
11396 _request_list_mutex.lock();
11397 locked = true;
11398 }
11399 /* continue if no dispatcher set (manual bm_receive_event) */
11400 if (_request_list[i].dispatcher == NULL)
11401 continue;
11402
11403 int buffer_handle = _request_list[i].buffer_handle;
11404
11405 /* must release the lock on the request list: user provided r.dispatcher() can add or remove event requests, and we will deadlock. K.O. */
11406 _request_list_mutex.unlock();
11407 locked = false;
11408
11409 do {
11410 /* receive event */
11411 int status = bm_receive_event_vec(buffer_handle, &vec, BM_NO_WAIT);
11412
11413 //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());
11414
11415 /* call user function if successful */
11416 if (status == BM_SUCCESS) {
11417 bm_dispatch_event(buffer_handle, (EVENT_HEADER*)vec.data());
11418 dispatched_something = TRUE;
11419 }
11420
11421 /* break if no more events */
11422 if (status == BM_ASYNC_RETURN)
11423 break;
11424
11425 /* break if corrupted event buffer */
11426 if (status == BM_TRUNCATED) {
11427 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());
11428 }
11429
11430 /* break if corrupted event buffer */
11431 if (status == BM_CORRUPTED)
11432 return SS_ABORT;
11433
11434 /* break if server died */
11435 if (status == RPC_NET_ERROR) {
11436 return SS_ABORT;
11437 }
11438
11439 /* stop after one second */
11440 if (ss_millitime() - start_time > 1000) {
11441 break;
11442 }
11443
11444 } while (TRUE);
11445 }
11446
11447 if (locked)
11448 _request_list_mutex.unlock();
11449
11450 if (dispatched_something)
11451 return BM_SUCCESS;
11452 else
11453 return BM_ASYNC_RETURN;
11454}
INT bm_receive_event_vec(INT buffer_handle, std::vector< char > *pvec, int timeout_msec)
Definition midas.cxx:11050
static void bm_dispatch_event(int buffer_handle, EVENT_HEADER *pevent)
Definition midas.cxx:8936
#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 11143 of file midas.cxx.

11143 {
11144 //printf("bm_push_buffer: buffer [%s], handle %d, callback %d\n", pbuf->buffer_header->name, buffer_handle, pbuf->callback);
11145
11146 /* return immediately if no callback routine is defined */
11147 if (!pbuf->callback)
11148 return BM_SUCCESS;
11149
11150 return bm_read_buffer(pbuf, buffer_handle, NULL, NULL, NULL, NULL, BM_NO_WAIT, 0, TRUE);
11151}
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:10392
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 10392 of file midas.cxx.

10392 {
10394
10395 int max_size = 0;
10396 if (buf_size) {
10397 max_size = *buf_size;
10398 *buf_size = 0;
10399 }
10400
10401 //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);
10402
10403 bm_lock_buffer_guard pbuf_guard(pbuf, true); // buffer is not locked
10404
10405 // NB: locking order is: 1st read cache lock, 2nd buffer lock, unlock in reverse order
10406
10407 /* look if there is anything in the cache */
10408 if (pbuf->read_cache_size > 0) {
10409
10411
10412 if (status != BM_SUCCESS)
10413 return status;
10414
10415 if (pbuf->read_cache_wp == 0) {
10416
10417 // lock buffer for the first time
10418
10419 if (!pbuf_guard.relock()) {
10420 pbuf->read_cache_mutex.unlock();
10421 return pbuf_guard.get_status();
10422 }
10423
10424 status = bm_fill_read_cache_locked(pbuf_guard, timeout_msec);
10425 if (status != BM_SUCCESS) {
10426 // unlock in correct order
10427 if (pbuf_guard.is_locked()) {
10428 // check if bm_wait_for_more_events() failed to relock the buffer
10429 pbuf_guard.unlock();
10430 }
10431 pbuf->read_cache_mutex.unlock();
10432 return status;
10433 }
10434
10435 // buffer remains locked here
10436 }
10437 EVENT_HEADER *pevent;
10438 int event_size;
10439 int total_size;
10440 if (bm_peek_read_cache_locked(pbuf, &pevent, &event_size, &total_size)) {
10441 if (pbuf_guard.is_locked()) {
10442 // do not need to keep the event buffer locked
10443 // when reading from the read cache
10444 pbuf_guard.unlock();
10445 }
10446 //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);
10448 if (buf) {
10449 if (event_size > max_size) {
10450 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);
10451 event_size = max_size;
10453 }
10454
10455 memcpy(buf, pevent, event_size);
10456
10457 if (buf_size) {
10458 *buf_size = event_size;
10459 }
10460 if (convert_flags) {
10461 bm_convert_event_header((EVENT_HEADER *) buf, convert_flags);
10462 }
10463 } else if (bufptr) {
10464 *bufptr = malloc(event_size);
10465 memcpy(*bufptr, pevent, event_size);
10467 } else if (vecptr) {
10468 vecptr->resize(0);
10469 char* cptr = (char*)pevent;
10470 vecptr->assign(cptr, cptr+event_size);
10471 }
10472 bm_incr_read_cache_locked(pbuf, total_size);
10473 pbuf->read_cache_mutex.unlock();
10474 if (dispatch) {
10475 // FIXME need to protect currently dispatched event against
10476 // another thread overwriting it by refilling the read cache
10477 bm_dispatch_event(buffer_handle, pevent);
10478 return BM_MORE_EVENTS;
10479 }
10480 // buffer is unlocked here
10481 return status;
10482 }
10483 pbuf->read_cache_mutex.unlock();
10484 }
10485
10486 /* we come here if the read cache is disabled */
10487 /* we come here if the next event is too big to fit into the read cache */
10488
10489 if (!pbuf_guard.is_locked()) {
10490 if (!pbuf_guard.relock())
10491 return pbuf_guard.get_status();
10492 }
10493
10494 EVENT_HEADER *event_buffer = NULL;
10495
10496 BUFFER_HEADER *pheader = pbuf->buffer_header;
10497
10498 BUFFER_CLIENT *pc = bm_get_my_client_locked(pbuf_guard);
10499
10500 while (1) {
10501 /* loop over events in the event buffer */
10502
10503 status = bm_wait_for_more_events_locked(pbuf_guard, pc, timeout_msec, FALSE);
10504
10505 if (status != BM_SUCCESS) {
10506 // implicit unlock
10507 return status;
10508 }
10509
10510 /* check if event at current read pointer matches a request */
10511
10512 EVENT_HEADER *pevent;
10513 int event_size;
10514 int total_size;
10515
10516 status = bm_peek_buffer_locked(pbuf, pheader, pc, &pevent, &event_size, &total_size);
10517 if (status == BM_CORRUPTED) {
10518 // implicit unlock
10519 return status;
10520 } else if (status != BM_SUCCESS) {
10521 /* event buffer is empty */
10522 break;
10523 }
10524
10525 BOOL is_requested = bm_check_requests(pc, pevent);
10526
10527 if (is_requested) {
10528 //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);
10529
10531
10532 if (buf) {
10533 if (event_size > max_size) {
10534 cm_msg(MERROR, "bm_read_buffer",
10535 "buffer size %d is smaller than event size %d, event truncated. buffer \"%s\"", max_size,
10536 event_size, pheader->name);
10537 event_size = max_size;
10539 }
10540
10541 bm_read_from_buffer_locked(pheader, pc->read_pointer, (char *) buf, event_size);
10542
10543 if (buf_size) {
10544 *buf_size = event_size;
10545 }
10546
10547 if (convert_flags) {
10548 bm_convert_event_header((EVENT_HEADER *) buf, convert_flags);
10549 }
10550
10551 pbuf->count_read++;
10552 pbuf->bytes_read += event_size;
10553 } else if (dispatch || bufptr) {
10554 assert(event_buffer == NULL); // make sure we only come here once
10555 event_buffer = (EVENT_HEADER *) malloc(event_size);
10557 pbuf->count_read++;
10558 pbuf->bytes_read += event_size;
10559 } else if (vecptr) {
10560 bm_read_from_buffer_locked(pheader, pc->read_pointer, vecptr, event_size);
10561 pbuf->count_read++;
10562 pbuf->bytes_read += event_size;
10563 }
10564
10565 int new_read_pointer = bm_incr_rp_no_check(pheader, pc->read_pointer, total_size);
10566 pc->read_pointer = new_read_pointer;
10567
10568 pheader->num_out_events++;
10569 /* exit loop over events */
10570 break;
10571 }
10572
10573 int new_read_pointer = bm_incr_rp_no_check(pheader, pc->read_pointer, total_size);
10574 pc->read_pointer = new_read_pointer;
10575 pheader->num_out_events++;
10576 }
10577
10578 /*
10579 If read pointer has been changed, it may have freed up some space
10580 for waiting producers. So check if free space is now more than 50%
10581 of the buffer size and wake waiting producers.
10582 */
10583
10584 bm_wakeup_producers_locked(pheader, pc);
10585
10586 pbuf_guard.unlock();
10587
10588 if (dispatch && event_buffer) {
10589 bm_dispatch_event(buffer_handle, event_buffer);
10590 free(event_buffer);
10591 event_buffer = NULL;
10592 return BM_MORE_EVENTS;
10593 }
10594
10595 if (bufptr && event_buffer) {
10596 *bufptr = event_buffer;
10597 event_buffer = NULL;
10599 }
10600
10601 if (event_buffer) {
10602 free(event_buffer);
10603 event_buffer = NULL;
10604 }
10605
10606 return status;
10607}
static void bm_convert_event_header(EVENT_HEADER *pevent, int convert_flags)
Definition midas.cxx:9182
static int bm_fill_read_cache_locked(bm_lock_buffer_guard &pbuf_guard, int timeout_msec)
Definition midas.cxx:9105
static BOOL bm_peek_read_cache_locked(BUFFER *pbuf, EVENT_HEADER **ppevent, int *pevent_size, int *ptotal_size)
Definition midas.cxx:8978
static void bm_incr_read_cache_locked(BUFFER *pbuf, int total_size)
Definition midas.cxx:8968
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 9049 of file midas.cxx.

9050{
9051 const char *pdata = (const char *) (pheader + 1);
9052
9053 if (rp + event_size <= pheader->size) {
9054 /* copy event to cache */
9055 memcpy(buf, pdata + rp, event_size);
9056 } else {
9057 /* event is splitted */
9058 int size = pheader->size - rp;
9059 memcpy(buf, pdata + rp, size);
9060 memcpy(buf + size, pdata, event_size - size);
9061 }
9062}
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 9064 of file midas.cxx.

9065{
9066 const char *pdata = (const char *) (pheader + 1);
9067
9068 if (rp + event_size <= pheader->size) {
9069 /* copy event to cache */
9070 vecptr->assign(pdata + rp, pdata + rp + event_size);
9071 } else {
9072 /* event is splitted */
9073 int size = pheader->size - rp;
9074 vecptr->assign(pdata + rp, pdata + rp + size);
9075 vecptr->insert(vecptr->end(), pdata, pdata + event_size - size);
9076 }
9077}

◆ 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:10891
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 10891 of file midas.cxx.

10891 {
10892 //printf("bm_receive_event: handle %d, async %d\n", buffer_handle, async_flag);
10893 if (rpc_is_remote()) {
10894 return bm_receive_event_rpc(buffer_handle, destination, buf_size, NULL, NULL, timeout_msec);
10895 }
10896#ifdef LOCAL_ROUTINES
10897 {
10899
10900 BUFFER *pbuf = bm_get_buffer("bm_receive_event", buffer_handle, &status);
10901
10902 if (!pbuf)
10903 return status;
10904
10905 int convert_flags = rpc_get_convert_flags();
10906
10907 status = bm_read_buffer(pbuf, buffer_handle, NULL, destination, buf_size, NULL, timeout_msec, convert_flags, FALSE);
10908 //printf("bm_receive_event: handle %d, async %d, status %d, size %d\n", buffer_handle, async_flag, status, *buf_size);
10909 return status;
10910 }
10911#else /* LOCAL_ROUTINES */
10912
10913 return BM_SUCCESS;
10914#endif
10915}
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:10611
INT rpc_get_convert_flags(void)
Definition midas.cxx:13263
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 10972 of file midas.cxx.

10972 {
10973 if (rpc_is_remote()) {
10974 return bm_receive_event_rpc(buffer_handle, NULL, NULL, ppevent, NULL, timeout_msec);
10975 }
10976#ifdef LOCAL_ROUTINES
10977 {
10979
10980 BUFFER *pbuf = bm_get_buffer("bm_receive_event_alloc", buffer_handle, &status);
10981
10982 if (!pbuf)
10983 return status;
10984
10985 int convert_flags = rpc_get_convert_flags();
10986
10987 return bm_read_buffer(pbuf, buffer_handle, (void **) ppevent, NULL, NULL, NULL, timeout_msec, convert_flags, FALSE);
10988 }
10989#else /* LOCAL_ROUTINES */
10990
10991 return BM_SUCCESS;
10992#endif
10993}
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 10611 of file midas.cxx.

10612{
10613 //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);
10614
10615 assert(_bm_max_event_size > sizeof(EVENT_HEADER));
10616
10617 void *xbuf = NULL;
10618 int xbuf_size = 0;
10619
10620 if (buf) {
10621 xbuf = buf;
10622 xbuf_size = *buf_size;
10623 } else if (ppevent) {
10624 *ppevent = (EVENT_HEADER*)malloc(_bm_max_event_size);
10625 xbuf_size = _bm_max_event_size;
10626 } else if (pvec) {
10627 pvec->resize(_bm_max_event_size);
10628 xbuf = pvec->data();
10629 xbuf_size = pvec->size();
10630 } else {
10631 assert(!"incorrect call to bm_receivent_event_rpc()");
10632 }
10633
10634 int status;
10635 DWORD time_start = ss_millitime();
10636 DWORD time_end = time_start + timeout_msec;
10637
10638 int xtimeout_msec = timeout_msec;
10639
10640 int zbuf_size = xbuf_size;
10641
10642 while (1) {
10643 if (timeout_msec == BM_WAIT) {
10644 xtimeout_msec = 1000;
10645 } else if (timeout_msec == BM_NO_WAIT) {
10646 xtimeout_msec = BM_NO_WAIT;
10647 } else {
10648 if (xtimeout_msec > 1000) {
10649 xtimeout_msec = 1000;
10650 }
10651 }
10652
10653 zbuf_size = xbuf_size;
10654
10655 status = rpc_call(RPC_BM_RECEIVE_EVENT, buffer_handle, xbuf, &zbuf_size, xtimeout_msec);
10656
10657 //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);
10658
10659 if (status == BM_ASYNC_RETURN) {
10660 if (timeout_msec == BM_WAIT) {
10661 // BM_WAIT means wait forever
10662 continue;
10663 } else if (timeout_msec == BM_NO_WAIT) {
10664 // BM_NO_WAIT means do not wait
10665 break;
10666 } else {
10667 DWORD now = ss_millitime();
10668 if (now >= time_end) {
10669 // timeout, return BM_ASYNC_RETURN
10670 break;
10671 }
10672
10673 DWORD remain = time_end - now;
10674
10675 if (remain < (DWORD)xtimeout_msec) {
10676 xtimeout_msec = remain;
10677 }
10678
10679 // keep asking for event...
10680 continue;
10681 }
10682 } else if (status == BM_SUCCESS) {
10683 // success, return BM_SUCCESS
10684 break;
10685 }
10686
10687 // RPC error
10688
10689 if (buf) {
10690 *buf_size = 0;
10691 } else if (ppevent) {
10692 free(*ppevent);
10693 *ppevent = NULL;
10694 } else if (pvec) {
10695 pvec->resize(0);
10696 } else {
10697 assert(!"incorrect call to bm_receivent_event_rpc()");
10698 }
10699
10700 return status;
10701 }
10702
10703 // status is BM_SUCCESS or BM_ASYNC_RETURN
10704
10705 if (buf) {
10706 *buf_size = zbuf_size;
10707 } else if (ppevent) {
10708 // nothing to do
10709 // ppevent = realloc(ppevent, xbuf_size); // shrink memory allocation
10710 } else if (pvec) {
10711 pvec->resize(zbuf_size);
10712 } else {
10713 assert(!"incorrect call to bm_receivent_event_rpc()");
10714 }
10715
10716 return status;
10717}
#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 10719 of file midas.cxx.

10720{
10721 //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);
10722
10723 std::vector<char> *pv;
10724
10725 if (pvec == NULL)
10726 pv = new std::vector<char>;
10727 else
10728 pv = pvec;
10729
10730 pv->clear();
10731
10732 int status;
10733 DWORD time_start = ss_millitime();
10734 DWORD time_end = time_start + timeout_msec;
10735
10736 int xtimeout_msec = timeout_msec;
10737
10738 while (1) {
10739 if (timeout_msec == BM_WAIT) {
10740 xtimeout_msec = 1000;
10741 } else if (timeout_msec == BM_NO_WAIT) {
10742 xtimeout_msec = BM_NO_WAIT;
10743 } else {
10744 if (xtimeout_msec > 1000) {
10745 xtimeout_msec = 1000;
10746 }
10747 }
10748
10749 status = rpc_call(RPC_BM_RECEIVE_EVENT_CXX, buffer_handle, pv, xtimeout_msec);
10750
10751 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());
10752
10753 if (status == BM_ASYNC_RETURN) {
10754 if (timeout_msec == BM_WAIT) {
10755 // BM_WAIT means wait forever
10756 continue;
10757 } else if (timeout_msec == BM_NO_WAIT) {
10758 // BM_NO_WAIT means do not wait
10759 break;
10760 } else {
10761 DWORD now = ss_millitime();
10762 if (now >= time_end) {
10763 // timeout, return BM_ASYNC_RETURN
10764 break;
10765 }
10766
10767 DWORD remain = time_end - now;
10768
10769 if (remain < (DWORD)xtimeout_msec) {
10770 xtimeout_msec = remain;
10771 }
10772
10773 // keep asking for event...
10774 continue;
10775 }
10776 } else if (status == BM_SUCCESS) {
10777 // success, return BM_SUCCESS
10778 break;
10779 }
10780
10781 // RPC error
10782
10783 if (buf) {
10784 *buf_size = 0;
10785 } else if (ppevent) {
10786 free(*ppevent);
10787 *ppevent = NULL;
10788 } else if (pvec) {
10789 pvec->clear();
10790 } else {
10791 assert(!"incorrect call to bm_receivent_event_rpc_cxx()");
10792 }
10793
10794 if (pvec == NULL)
10795 delete pv;
10796
10797 return status;
10798 }
10799
10800 // status is BM_SUCCESS or BM_ASYNC_RETURN
10801
10802 if (buf) {
10803 if (pv->size() > (size_t)*buf_size) {
10805 memcpy(buf, pv->data(), *buf_size);
10806 } else {
10807 *buf_size = pv->size();
10808 memcpy(buf, pv->data(), *buf_size);
10809 }
10810 } else if (ppevent) {
10811 if (*ppevent == NULL) {
10812 *ppevent = (EVENT_HEADER*)malloc(pv->size());
10813 assert(*ppevent != NULL);
10814 memcpy(*ppevent, pv->data(), pv->size());
10815 } else {
10816 *ppevent = (EVENT_HEADER*)realloc(*ppevent, pv->size()); // shrink memory allocation
10817 assert(*ppevent != NULL);
10818 memcpy(*ppevent, pv->data(), pv->size());
10819 }
10820 } else if (pvec) {
10821 // nothing to do
10822 } else {
10823 assert(!"incorrect call to bm_receivent_event_rpc()");
10824 }
10825
10826 if (!pvec)
10827 delete pv;
10828
10829 return status;
10830}
#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 11050 of file midas.cxx.

11050 {
11051 if (rpc_is_remote()) {
11052 return bm_receive_event_rpc(buffer_handle, NULL, NULL, NULL, pvec, timeout_msec);
11053 }
11054#ifdef LOCAL_ROUTINES
11055 {
11057
11058 BUFFER *pbuf = bm_get_buffer("bm_receive_event_vec", buffer_handle, &status);
11059
11060 if (!pbuf)
11061 return status;
11062
11063 int convert_flags = rpc_get_convert_flags();
11064
11065 return bm_read_buffer(pbuf, buffer_handle, NULL, NULL, NULL, pvec, timeout_msec, convert_flags, FALSE);
11066 }
11067#else /* LOCAL_ROUTINES */
11068 return BM_SUCCESS;
11069#endif
11070}
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 6107 of file midas.cxx.

6107 {
6108 int k, nc;
6109 BUFFER_CLIENT *pbctmp;
6110
6111 /* clear entry from client structure in buffer header */
6112 memset(&(pheader->client[j]), 0, sizeof(BUFFER_CLIENT));
6113
6114 /* calculate new max_client_index entry */
6115 for (k = MAX_CLIENTS - 1; k >= 0; k--)
6116 if (pheader->client[k].pid != 0)
6117 break;
6118 pheader->max_client_index = k + 1;
6119
6120 /* count new number of clients */
6121 for (k = MAX_CLIENTS - 1, nc = 0; k >= 0; k--)
6122 if (pheader->client[k].pid != 0)
6123 nc++;
6124 pheader->num_clients = nc;
6125
6126 /* check if anyone is waiting and wake him up */
6127 pbctmp = pheader->client;
6128
6129 for (k = 0; k < pheader->max_client_index; k++, pbctmp++)
6130 if (pbctmp->pid && (pbctmp->write_wait || pbctmp->read_wait))
6131 ss_resume(pbctmp->port, "B ");
6132}
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 8631 of file midas.cxx.

8631 {
8632 if (rpc_is_remote())
8633 return rpc_call(RPC_BM_REMOVE_EVENT_REQUEST, buffer_handle, request_id);
8634
8635#ifdef LOCAL_ROUTINES
8636 {
8637 int status = 0;
8638
8639 BUFFER *pbuf = bm_get_buffer("bm_remove_event_request", buffer_handle, &status);
8640
8641 if (!pbuf)
8642 return status;
8643
8644 /* lock buffer */
8645 bm_lock_buffer_guard pbuf_guard(pbuf);
8646
8647 if (!pbuf_guard.is_locked())
8648 return pbuf_guard.get_status();
8649
8650 INT i, deleted;
8651
8652 /* get a pointer to the proper client structure */
8653 BUFFER_CLIENT *pclient = bm_get_my_client_locked(pbuf_guard);
8654
8655 /* check all requests and set to zero if matching */
8656 for (i = 0, deleted = 0; i < pclient->max_request_index; i++)
8657 if (pclient->event_request[i].valid && pclient->event_request[i].id == request_id) {
8658 memset(&pclient->event_request[i], 0, sizeof(EVENT_REQUEST));
8659 deleted++;
8660 }
8661
8662 /* calculate new max_request_index entry */
8663 for (i = MAX_EVENT_REQUESTS - 1; i >= 0; i--)
8664 if (pclient->event_request[i].valid)
8665 break;
8666
8667 pclient->max_request_index = i + 1;
8668
8669 /* calculate new all_flag */
8670 pclient->all_flag = FALSE;
8671
8672 for (i = 0; i < pclient->max_request_index; i++)
8673 if (pclient->event_request[i].valid && (pclient->event_request[i].sampling_type & GET_ALL)) {
8674 pclient->all_flag = TRUE;
8675 break;
8676 }
8677
8678 pbuf->get_all_flag = pclient->all_flag;
8679
8680 if (!deleted)
8681 return BM_NOT_FOUND;
8682 }
8683#endif /* LOCAL_ROUTINES */
8684
8685 return BM_SUCCESS;
8686}
#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 8578 of file midas.cxx.

8582{
8583 assert(request_id != NULL);
8584
8585 EventRequest r;
8586 r.buffer_handle = buffer_handle;
8587 r.event_id = event_id;
8589 r.dispatcher = func;
8590
8591 {
8592 std::lock_guard<std::mutex> guard(_request_list_mutex);
8593
8594 bool found = false;
8595
8596 // find deleted entry
8597 for (size_t i = 0; i < _request_list.size(); i++) {
8598 if (_request_list[i].buffer_handle == 0) {
8599 _request_list[i] = r;
8600 *request_id = i;
8601 found = true;
8602 break;
8603 }
8604 }
8605
8606 if (!found) { // not found
8607 *request_id = _request_list.size();
8608 _request_list.push_back(r);
8609 }
8610
8611 // implicit unlock()
8612 }
8613
8614 /* add request in buffer structure */
8615 int status = bm_add_event_request(buffer_handle, event_id, trigger_mask, sampling_type, func, *request_id);
8616 if (status != BM_SUCCESS)
8617 return status;
8618
8619 return BM_SUCCESS;
8620}
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:8427
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 6463 of file midas.cxx.

6463 {
6464 BUFFER_HEADER *pheader = pbuf->buffer_header;
6465
6466 //printf("bm_reset_buffer: buffer \"%s\"\n", pheader->name);
6467
6468 pheader->read_pointer = 0;
6469 pheader->write_pointer = 0;
6470
6471 int i;
6472 for (i = 0; i < pheader->max_client_index; i++) {
6473 BUFFER_CLIENT *pc = pheader->client + i;
6474 if (pc->pid) {
6475 pc->read_pointer = 0;
6476 }
6477 }
6478}
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 9791 of file midas.cxx.

9792{
9793 const DWORD MAX_DATA_SIZE = (0x7FFFFFF0 - 16); // event size computations are not 32-bit clean, limit event size to 2GB. K.O.
9794 const DWORD data_size = pevent->data_size; // 32-bit unsigned value
9795
9796 if (data_size == 0) {
9797 cm_msg(MERROR, "bm_send_event", "invalid event data size zero");
9798 return BM_INVALID_SIZE;
9799 }
9800
9801 if (data_size > MAX_DATA_SIZE) {
9802 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);
9803 return BM_INVALID_SIZE;
9804 }
9805
9806 const size_t event_size = sizeof(EVENT_HEADER) + data_size;
9807
9808 //printf("bm_send_event: pevent %p, data_size %d, event_size %d, buf_size %d\n", pevent, data_size, event_size, unused);
9809
9810 if (rpc_is_remote()) {
9811 //return bm_send_event_rpc(buffer_handle, pevent, event_size, timeout_msec);
9812 return rpc_send_event_sg(buffer_handle, 1, (char**)&pevent, &event_size);
9813 } else {
9814 return bm_send_event_sg(buffer_handle, 1, (char**)&pevent, &event_size, timeout_msec);
9815 }
9816}
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:9891
#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:14475
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:9791
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 9891 of file midas.cxx.

9892{
9893 if (rpc_is_remote())
9894 return rpc_send_event_sg(buffer_handle, sg_n, sg_ptr, sg_len);
9895
9896 if (sg_n < 1) {
9897 cm_msg(MERROR, "bm_send_event", "invalid sg_n %d", sg_n);
9898 return BM_INVALID_SIZE;
9899 }
9900
9901 if (sg_ptr[0] == NULL) {
9902 cm_msg(MERROR, "bm_send_event", "invalid sg_ptr[0] is NULL");
9903 return BM_INVALID_SIZE;
9904 }
9905
9906 if (sg_len[0] < sizeof(EVENT_HEADER)) {
9907 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));
9908 return BM_INVALID_SIZE;
9909 }
9910
9911 const EVENT_HEADER* pevent = (const EVENT_HEADER*)sg_ptr[0];
9912
9913 const DWORD MAX_DATA_SIZE = (0x7FFFFFF0 - 16); // event size computations are not 32-bit clean, limit event size to 2GB. K.O.
9914 const DWORD data_size = pevent->data_size; // 32-bit unsigned value
9915
9916 if (data_size == 0) {
9917 cm_msg(MERROR, "bm_send_event", "invalid event data size zero");
9918 return BM_INVALID_SIZE;
9919 }
9920
9921 if (data_size > MAX_DATA_SIZE) {
9922 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);
9923 return BM_INVALID_SIZE;
9924 }
9925
9926 const size_t event_size = sizeof(EVENT_HEADER) + data_size;
9927
9928 size_t count = 0;
9929 for (int i=0; i<sg_n; i++) {
9930 count += sg_len[i];
9931 }
9932
9933 if (count != event_size) {
9934 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);
9935 return BM_INVALID_SIZE;
9936 }
9937
9938 //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);
9939
9940#ifdef LOCAL_ROUTINES
9941 {
9942 int status = 0;
9943 const size_t total_size = ALIGN8(event_size);
9944
9945 BUFFER *pbuf = bm_get_buffer("bm_send_event_sg", buffer_handle, &status);
9946
9947 if (!pbuf)
9948 return status;
9949
9950 /* round up total_size to next DWORD boundary */
9951 //int total_size = ALIGN8(event_size);
9952
9953 /* check if write cache is enabled */
9954 if (pbuf->write_cache_size) {
9956
9957 if (status != BM_SUCCESS)
9958 return status;
9959
9960 /* check if write cache is enabled */
9961 if (pbuf->write_cache_size) {
9963 bool too_big = event_size > max_event_size;
9964
9965 //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);
9966
9967 /* if this event does not fit into the write cache, flush the write cache */
9968 if (pbuf->write_cache_wp > 0 && (pbuf->write_cache_wp + total_size > pbuf->write_cache_size || too_big)) {
9969 //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);
9970
9971 bm_lock_buffer_guard pbuf_guard(pbuf);
9972
9973 if (!pbuf_guard.is_locked()) {
9974 pbuf->write_cache_mutex.unlock();
9975 return pbuf_guard.get_status();
9976 }
9977
9978 int status = bm_flush_cache_locked(pbuf_guard, timeout_msec);
9979
9980 if (pbuf_guard.is_locked()) {
9981 // check if bm_wait_for_free_space() failed to relock the buffer
9982 pbuf_guard.unlock();
9983 }
9984
9985 if (status != BM_SUCCESS) {
9986 pbuf->write_cache_mutex.unlock();
9987 // bm_flush_cache() failed: timeout in bm_wait_for_free_space() or write cache size is bigger than buffer size or buffer was closed.
9988 if (status == BM_NO_MEMORY)
9989 cm_msg(MERROR, "bm_send_event", "write cache size is bigger than buffer size");
9990 return status;
9991 }
9992
9993 // write cache must be empty here
9994 assert(pbuf->write_cache_wp == 0);
9995 }
9996
9997 /* write this event into the write cache, if it is not too big and if it fits */
9998 if (!too_big && pbuf->write_cache_wp + total_size <= pbuf->write_cache_size) {
9999 //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);
10000
10001 char* wptr = pbuf->write_cache + pbuf->write_cache_wp;
10002
10003 for (int i=0; i<sg_n; i++) {
10004 memcpy(wptr, sg_ptr[i], sg_len[i]);
10005 wptr += sg_len[i];
10006 }
10007
10008 pbuf->write_cache_wp += total_size;
10009
10010 pbuf->write_cache_mutex.unlock();
10011 return BM_SUCCESS;
10012 }
10013 }
10014
10015 /* event did not fit into the write cache, we flushed the write cache and we send it directly to shared memory */
10016 pbuf->write_cache_mutex.unlock();
10017 }
10018
10019 /* we come here only for events that are too big to fit into the cache */
10020
10021 /* lock the buffer */
10022 bm_lock_buffer_guard pbuf_guard(pbuf);
10023
10024 if (!pbuf_guard.is_locked()) {
10025 return pbuf_guard.get_status();
10026 }
10027
10028 /* calculate some shorthands */
10029 BUFFER_HEADER *pheader = pbuf->buffer_header;
10030
10031#if 0
10033 if (status != BM_SUCCESS) {
10034 printf("bm_send_event: corrupted 111!\n");
10035 abort();
10036 }
10037#endif
10038
10039 /* check if buffer is large enough */
10040 if (total_size >= (size_t)pheader->size) {
10041 pbuf_guard.unlock(); // unlock before cm_msg()
10042 cm_msg(MERROR, "bm_send_event", "total event size (%d) larger than size (%d) of buffer \'%s\'", (int)total_size, pheader->size, pheader->name);
10043 return BM_NO_MEMORY;
10044 }
10045
10046 status = bm_wait_for_free_space_locked(pbuf_guard, timeout_msec, total_size, false);
10047
10048 if (status != BM_SUCCESS) {
10049 // implicit unlock
10050 return status;
10051 }
10052
10053#if 0
10055 if (status != BM_SUCCESS) {
10056 printf("bm_send_event: corrupted 222!\n");
10057 abort();
10058 }
10059#endif
10060
10061 int old_write_pointer = pheader->write_pointer;
10062
10063 bm_write_to_buffer_locked(pheader, sg_n, sg_ptr, sg_len, total_size);
10064
10065 /* write pointer was incremented, but there should
10066 * always be some free space in the buffer and the
10067 * write pointer should never cacth up to the read pointer:
10068 * the rest of the code gets confused this happens (buffer 100% full)
10069 * as it is write_pointer == read_pointer can be either
10070 * 100% full or 100% empty. My solution: never fill
10071 * the buffer to 100% */
10072 assert(pheader->write_pointer != pheader->read_pointer);
10073
10074 /* send wake up messages to all clients that want this event */
10075 int i;
10076 for (i = 0; i < pheader->max_client_index; i++) {
10077 BUFFER_CLIENT *pc = pheader->client + i;
10078 int request_id = bm_find_first_request_locked(pc, pevent);
10079 bm_notify_reader_locked(pheader, pc, old_write_pointer, request_id);
10080 }
10081
10082#if 0
10084 if (status != BM_SUCCESS) {
10085 printf("bm_send_event: corrupted 333!\n");
10086 abort();
10087 }
10088#endif
10089
10090 /* update statistics */
10091 pheader->num_in_events++;
10092 pbuf->count_sent += 1;
10093 pbuf->bytes_sent += total_size;
10094 }
10095#endif /* LOCAL_ROUTINES */
10096
10097 return BM_SUCCESS;
10098}
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 9818 of file midas.cxx.

9819{
9820 const char* cptr = event.data();
9821 size_t clen = event.size();
9822 return bm_send_event_sg(buffer_handle, 1, &cptr, &clen, timeout_msec);
9823}
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 9825 of file midas.cxx.

9826{
9827 int sg_n = event.size();
9828 const char* sg_ptr[sg_n];
9829 size_t sg_len[sg_n];
9830 for (int i=0; i<sg_n; i++) {
9831 sg_ptr[i] = event[i].data();
9832 sg_len[i] = event[i].size();
9833 }
9834 return bm_send_event_sg(buffer_handle, sg_n, sg_ptr, sg_len, timeout_msec);
9835}
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 8253 of file midas.cxx.

8255{
8256 if (rpc_is_remote())
8257 return rpc_call(RPC_BM_SET_CACHE_SIZE, buffer_handle, read_size, write_size);
8258
8259#ifdef LOCAL_ROUTINES
8260 {
8261 int status = 0;
8262
8263 BUFFER *pbuf = bm_get_buffer("bm_set_cache_size", buffer_handle, &status);
8264
8265 if (!pbuf)
8266 return status;
8267
8268 /* lock pbuf for local access. we do not lock buffer semaphore because we do not touch the shared memory */
8269
8271
8272 if (status != BM_SUCCESS)
8273 return status;
8274
8275 if (write_size < 0)
8276 write_size = 0;
8277
8278 if (write_size > 0) {
8279 if (write_size < MIN_WRITE_CACHE_SIZE) {
8280 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);
8281 write_size = MIN_WRITE_CACHE_SIZE;
8282 }
8283 }
8284
8285 size_t max_write_size = pbuf->buffer_header->size/MAX_WRITE_CACHE_SIZE_DIV;
8286
8287 if (write_size > max_write_size) {
8288 size_t new_write_size = max_write_size;
8289 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);
8290 write_size = new_write_size;
8291 }
8292
8293 pbuf->buffer_mutex.unlock();
8294
8295 /* resize read cache */
8296
8298
8299 if (status != BM_SUCCESS) {
8300 return status;
8301 }
8302
8303 if (pbuf->read_cache_size > 0) {
8304 free(pbuf->read_cache);
8305 pbuf->read_cache = NULL;
8306 }
8307
8308 if (read_size > 0) {
8309 pbuf->read_cache = (char *) malloc(read_size);
8310 if (pbuf->read_cache == NULL) {
8311 pbuf->read_cache_size = 0;
8312 pbuf->read_cache_rp = 0;
8313 pbuf->read_cache_wp = 0;
8314 pbuf->read_cache_mutex.unlock();
8315 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);
8316 return BM_NO_MEMORY;
8317 }
8318 }
8319
8320 pbuf->read_cache_size = read_size;
8321 pbuf->read_cache_rp = 0;
8322 pbuf->read_cache_wp = 0;
8323
8324 pbuf->read_cache_mutex.unlock();
8325
8326 /* resize the write cache */
8327
8329
8330 if (status != BM_SUCCESS)
8331 return status;
8332
8333 // FIXME: should flush the write cache!
8334 if (pbuf->write_cache_size && pbuf->write_cache_wp > 0) {
8335 cm_msg(MERROR, "bm_set_cache_size", "buffer \"%s\" lost %zu bytes from the write cache", pbuf->buffer_name, pbuf->write_cache_wp);
8336 }
8337
8338 /* manage write cache */
8339 if (pbuf->write_cache_size > 0) {
8340 free(pbuf->write_cache);
8341 pbuf->write_cache = NULL;
8342 }
8343
8344 if (write_size > 0) {
8345 pbuf->write_cache = (char *) M_MALLOC(write_size);
8346 if (pbuf->write_cache == NULL) {
8347 pbuf->write_cache_size = 0;
8348 pbuf->write_cache_rp = 0;
8349 pbuf->write_cache_wp = 0;
8350 pbuf->write_cache_mutex.unlock();
8351 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);
8352 return BM_NO_MEMORY;
8353 }
8354 }
8355
8356 pbuf->write_cache_size = write_size;
8357 pbuf->write_cache_rp = 0;
8358 pbuf->write_cache_wp = 0;
8359
8360 pbuf->write_cache_mutex.unlock();
8361 }
8362#endif /* LOCAL_ROUTINES */
8363
8364 return BM_SUCCESS;
8365}
static int bm_lock_buffer_mutex(BUFFER *pbuf)
Definition midas.cxx:8059
#define RPC_BM_SET_CACHE_SIZE
Definition mrpc.h:42
#define M_MALLOC(x)
Definition midas.h:1487
#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 11074 of file midas.cxx.

11075{
11076 /* clear read cache */
11077 if (pbuf->read_cache_size > 0) {
11078
11080
11081 if (status != BM_SUCCESS)
11082 return status;
11083
11084 pbuf->read_cache_rp = 0;
11085 pbuf->read_cache_wp = 0;
11086
11087 pbuf->read_cache_mutex.unlock();
11088 }
11089
11090 bm_lock_buffer_guard pbuf_guard(pbuf);
11091
11092 if (!pbuf_guard.is_locked())
11093 return pbuf_guard.get_status();
11094
11095 BUFFER_HEADER *pheader = pbuf->buffer_header;
11096
11097 /* forward read pointer to global write pointer */
11098 BUFFER_CLIENT *pclient = bm_get_my_client_locked(pbuf_guard);
11099 pclient->read_pointer = pheader->write_pointer;
11100
11101 return BM_SUCCESS;
11102}
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 11115 of file midas.cxx.

11115 {
11116 if (rpc_is_remote())
11117 return rpc_call(RPC_BM_SKIP_EVENT, buffer_handle);
11118
11119#ifdef LOCAL_ROUTINES
11120 {
11121 int status = 0;
11122
11123 BUFFER *pbuf = bm_get_buffer("bm_skip_event", buffer_handle, &status);
11124
11125 if (!pbuf)
11126 return status;
11127
11128 return bm_skip_event(pbuf);
11129 }
11130#endif
11131
11132 return BM_SUCCESS;
11133}
#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 6189 of file midas.cxx.

6189 {
6190 int pid = ss_getpid();
6191
6192 std::vector<BUFFER*> mybuffers;
6193
6194 gBuffersMutex.lock();
6195 mybuffers = gBuffers;
6196 gBuffersMutex.unlock();
6197
6198 for (BUFFER* pbuf : mybuffers) {
6199 if (!pbuf)
6200 continue;
6201 if (pbuf->attached) {
6202
6203 bm_lock_buffer_guard pbuf_guard(pbuf);
6204
6205 if (!pbuf_guard.is_locked())
6206 continue;
6207
6208 BUFFER_HEADER *pheader = pbuf->buffer_header;
6209 for (int j = 0; j < pheader->max_client_index; j++) {
6210 BUFFER_CLIENT *pclient = pheader->client + j;
6211 if (pclient->pid == pid) {
6212 pclient->last_activity = millitime;
6213 }
6214 }
6215 }
6216 }
6217}
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 8833 of file midas.cxx.

8833 {
8834 assert(caller_name);
8835
8836 /* calculate global read pointer as "minimum" of client read pointers */
8837 int min_rp = pheader->write_pointer;
8838
8839 int i;
8840 for (i = 0; i < pheader->max_client_index; i++) {
8841 BUFFER_CLIENT *pc = pheader->client + i;
8842 if (pc->pid) {
8844
8845#if 0
8846 printf("bm_update_read_pointer: [%s] rp %d, wp %d, size %d, min_rp %d, client [%s] rp %d\n",
8847 pheader->name,
8848 pheader->read_pointer,
8849 pheader->write_pointer,
8850 pheader->size,
8851 min_rp,
8852 pc->name,
8853 pc->read_pointer);
8854#endif
8855
8856 if (pheader->read_pointer <= pheader->write_pointer) {
8857 // normal pointers
8858 if (pc->read_pointer < min_rp)
8859 min_rp = pc->read_pointer;
8860 } else {
8861 // inverted pointers
8862 if (pc->read_pointer <= pheader->write_pointer) {
8863 // clients 3 and 4
8864 if (pc->read_pointer < min_rp)
8865 min_rp = pc->read_pointer;
8866 } else {
8867 // clients 1 and 2
8868 int xptr = pc->read_pointer - pheader->size;
8869 if (xptr < min_rp)
8870 min_rp = xptr;
8871 }
8872 }
8873 }
8874 }
8875
8876 if (min_rp < 0)
8877 min_rp += pheader->size;
8878
8879 assert(min_rp >= 0);
8880 assert(min_rp < pheader->size);
8881
8882 if (min_rp == pheader->read_pointer) {
8883 return FALSE;
8884 }
8885
8886#if 0
8887 printf("bm_update_read_pointer: [%s] rp %d, wp %d, size %d, new_rp %d, moved\n",
8888 pheader->name,
8889 pheader->read_pointer,
8890 pheader->write_pointer,
8891 pheader->size,
8892 min_rp);
8893#endif
8894
8895 pheader->read_pointer = min_rp;
8896
8897 return TRUE;
8898}
static void bm_validate_client_pointers_locked(const BUFFER_HEADER *pheader, BUFFER_CLIENT *pclient)
Definition midas.cxx:8735
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 6379 of file midas.cxx.

6379 {
6380 const BUFFER_HEADER *pheader = pbuf->buffer_header;
6381 const char *pdata = (const char *) (pheader + 1);
6382
6383 //printf("bm_validate_buffer: buffer \"%s\"\n", pheader->name);
6384
6385 //printf("size: %d, rp: %d, wp: %d\n", pheader->size, pheader->read_pointer, pheader->write_pointer);
6386
6387 //printf("clients: max: %d, num: %d, MAX_CLIENTS: %d\n", pheader->max_client_index, pheader->num_clients, MAX_CLIENTS);
6388
6389 if (pheader->read_pointer < 0 || pheader->read_pointer >= pheader->size) {
6390 cm_msg(MERROR, "bm_validate_buffer",
6391 "buffer \"%s\" is corrupted: invalid read pointer %d. Size %d, write pointer %d", pheader->name,
6392 pheader->read_pointer, pheader->size, pheader->write_pointer);
6393 return BM_CORRUPTED;
6394 }
6395
6396 if (pheader->write_pointer < 0 || pheader->write_pointer >= pheader->size) {
6397 cm_msg(MERROR, "bm_validate_buffer",
6398 "buffer \"%s\" is corrupted: invalid write pointer %d. Size %d, read pointer %d", pheader->name,
6399 pheader->write_pointer, pheader->size, pheader->read_pointer);
6400 return BM_CORRUPTED;
6401 }
6402
6403 if (!bm_validate_rp("bm_validate_buffer_locked", pheader, pheader->read_pointer)) {
6404 cm_msg(MERROR, "bm_validate_buffer", "buffer \"%s\" is corrupted: read pointer %d is invalid", pheader->name,
6405 pheader->read_pointer);
6406 return BM_CORRUPTED;
6407 }
6408
6409 int rp = pheader->read_pointer;
6410 int rp0 = -1;
6411 while (rp != pheader->write_pointer) {
6412 if (!bm_validate_rp("bm_validate_buffer_locked", pheader, rp)) {
6413 cm_msg(MERROR, "bm_validate_buffer", "buffer \"%s\" is corrupted: invalid rp %d, last good event at rp %d",
6414 pheader->name, rp, rp0);
6415 return BM_CORRUPTED;
6416 }
6417 //bm_print_event(pdata, rp);
6418 int rp1 = bm_next_rp("bm_validate_buffer_locked", pheader, pdata, rp);
6419 if (rp1 < 0) {
6420 cm_msg(MERROR, "bm_validate_buffer",
6421 "buffer \"%s\" is corrupted: invalid event at rp %d, last good event at rp %d", pheader->name, rp, rp0);
6422 return BM_CORRUPTED;
6423 }
6424 rp0 = rp;
6425 rp = rp1;
6426 }
6427
6428 int i;
6429 for (i = 0; i < MAX_CLIENTS; i++) {
6430 const BUFFER_CLIENT *c = &pheader->client[i];
6431 if (c->pid == 0)
6432 continue;
6433 BOOL get_all = FALSE;
6434 int j;
6435 for (j = 0; j < MAX_EVENT_REQUESTS; j++) {
6436 const EVENT_REQUEST *r = &c->event_request[j];
6437 if (!r->valid)
6438 continue;
6439 BOOL xget_all = r->sampling_type == GET_ALL;
6440 get_all = (get_all || xget_all);
6441 //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);
6442 }
6443
6444 int rp = c->read_pointer;
6445 int rp0 = -1;
6446 while (rp != pheader->write_pointer) {
6447 //bm_print_event(pdata, rp);
6448 int rp1 = bm_next_rp("bm_validate_buffer_locked", pheader, pdata, rp);
6449 if (rp1 < 0) {
6450 cm_msg(MERROR, "bm_validate_buffer",
6451 "buffer \"%s\" is corrupted for client \"%s\" rp %d: invalid event at rp %d, last good event at rp %d",
6452 pheader->name, c->name, c->read_pointer, rp, rp0);
6453 return BM_CORRUPTED;
6454 }
6455 rp0 = rp;
6456 rp = rp1;
6457 }
6458 }
6459
6460 return BM_SUCCESS;
6461}
static BOOL bm_validate_rp(const char *who, const BUFFER_HEADER *pheader, int rp)
Definition midas.cxx:6261
static int bm_next_rp(const char *who, const BUFFER_HEADER *pheader, const char *pdata, int rp)
Definition midas.cxx:6328
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 5994 of file midas.cxx.

5995{
5996 const BUFFER *pbuf = pbuf_guard.get_pbuf();
5997
5998 bool badindex = false;
5999 bool badclient = false;
6000
6001 int idx = pbuf->client_index;
6002
6003 if (idx < 0) {
6004 badindex = true;
6005 } else if (idx > pbuf->buffer_header->max_client_index) {
6006 badindex = true;
6007 } else {
6008 BUFFER_CLIENT *pclient = &pbuf->buffer_header->client[idx];
6009 if (pclient->name[0] == 0)
6010 badclient = true;
6011 else if (pclient->pid != ss_getpid())
6012 badclient = true;
6013
6014 //if (strcmp(pclient->name,"mdump")==0) {
6015 // for (int i=0; i<15; i++) {
6016 // printf("sleep %d\n", i);
6017 // ::sleep(1);
6018 // }
6019 //}
6020 }
6021
6022#if 0
6023 if (badindex) {
6024 printf("bm_validate_client_index: pbuf=%p, buf_name \"%s\", client_index=%d, max_client_index=%d, badindex %d, pid=%d\n",
6025 pbuf, pbuf->buffer_header->name, pbuf->client_index, pbuf->buffer_header->max_client_index,
6026 badindex, ss_getpid());
6027 } else if (badclient) {
6028 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",
6029 pbuf, pbuf->buffer_header->name, pbuf->client_index, pbuf->buffer_header->max_client_index,
6030 pbuf->buffer_header->client[idx].name, pbuf->buffer_header->client[idx].pid,
6031 ss_getpid(), badclient);
6032 } else {
6033 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",
6034 pbuf, pbuf->buffer_header->name, pbuf->client_index, pbuf->buffer_header->max_client_index,
6035 pbuf->buffer_header->client[idx].name, pbuf->buffer_header->client[idx].pid,
6036 ss_getpid());
6037 }
6038#endif
6039
6040 if (badindex || badclient) {
6041 static int prevent_recursion = 1;
6042
6043 if (prevent_recursion) {
6044 prevent_recursion = 0;
6045
6046 if (badindex) {
6047 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());
6048 } else {
6049 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());
6050 }
6051
6052 cm_msg(MERROR, "bm_validate_client_index", "Maybe this client was removed by a timeout. See midas.log. Cannot continue, aborting...");
6053 }
6054
6055 if (badindex) {
6056 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());
6057 } else {
6058 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());
6059 }
6060
6061 fprintf(stderr, "bm_validate_client_index: Maybe this client was removed by a timeout. See midas.log. Cannot continue, aborting...\n");
6062
6063 pbuf_guard.unlock();
6064
6065 abort();
6066 }
6067
6068 return idx;
6069}
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 8735 of file midas.cxx.

8735 {
8736 assert(pheader->read_pointer >= 0 && pheader->read_pointer <= pheader->size);
8737 assert(pclient->read_pointer >= 0 && pclient->read_pointer <= pheader->size);
8738
8739 if (pheader->read_pointer <= pheader->write_pointer) {
8740
8741 if (pclient->read_pointer < pheader->read_pointer) {
8742 cm_msg(MINFO, "bm_validate_client_pointers",
8743 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, write pointer %d, size %d",
8744 pclient->name,
8745 pheader->name, pclient->read_pointer, pheader->read_pointer, pheader->write_pointer, pheader->size);
8746
8747 pclient->read_pointer = pheader->read_pointer;
8748 }
8749
8750 if (pclient->read_pointer > pheader->write_pointer) {
8751 cm_msg(MINFO, "bm_validate_client_pointers",
8752 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, read pointer %d, size %d",
8753 pclient->name,
8754 pheader->name, pclient->read_pointer, pheader->write_pointer, pheader->read_pointer, pheader->size);
8755
8756 pclient->read_pointer = pheader->write_pointer;
8757 }
8758
8759 } else {
8760
8761 if (pclient->read_pointer < 0) {
8762 cm_msg(MINFO, "bm_validate_client_pointers",
8763 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, write pointer %d, size %d",
8764 pclient->name,
8765 pheader->name, pclient->read_pointer, pheader->read_pointer, pheader->write_pointer, pheader->size);
8766
8767 pclient->read_pointer = pheader->read_pointer;
8768 }
8769
8770 if (pclient->read_pointer >= pheader->size) {
8771 cm_msg(MINFO, "bm_validate_client_pointers",
8772 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, write pointer %d, size %d",
8773 pclient->name,
8774 pheader->name, pclient->read_pointer, pheader->read_pointer, pheader->write_pointer, pheader->size);
8775
8776 pclient->read_pointer = pheader->read_pointer;
8777 }
8778
8779 if (pclient->read_pointer > pheader->write_pointer && pclient->read_pointer < pheader->read_pointer) {
8780 cm_msg(MINFO, "bm_validate_client_pointers",
8781 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d, write pointer %d, size %d",
8782 pclient->name,
8783 pheader->name, pclient->read_pointer, pheader->read_pointer, pheader->write_pointer, pheader->size);
8784
8785 pclient->read_pointer = pheader->read_pointer;
8786 }
8787 }
8788}
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 6261 of file midas.cxx.

6261 {
6262 if (rp < 0 || rp > pheader->size) {
6263 cm_msg(MERROR, "bm_validate_rp",
6264 "error: buffer \"%s\" is corrupted: rp %d is invalid. buffer read_pointer %d, write_pointer %d, size %d, called from %s",
6265 pheader->name,
6266 rp,
6267 pheader->read_pointer,
6268 pheader->write_pointer,
6269 pheader->size,
6270 who);
6271 return FALSE;
6272 }
6273
6274 if ((rp + (int) sizeof(EVENT_HEADER)) > pheader->size) {
6275 // note ">" here, has to match bm_incr_rp() and bm_write_to_buffer()
6276 cm_msg(MERROR, "bm_validate_rp",
6277 "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",
6278 pheader->name,
6279 rp,
6280 (int) (rp + sizeof(EVENT_HEADER) - pheader->size),
6281 pheader->read_pointer,
6282 pheader->write_pointer,
6283 pheader->size,
6284 who);
6285 return FALSE;
6286 }
6287
6288 return TRUE;
6289}
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 9193 of file midas.cxx.

9194{
9195 // return values:
9196 // BM_SUCCESS - have "requested_space" bytes free in the buffer
9197 // BM_CORRUPTED - shared memory is corrupted
9198 // BM_NO_MEMORY - asked for more than buffer size
9199 // BM_ASYNC_RETURN - timeout waiting for free space
9200 // BM_INVALID_HANDLE - buffer was closed (locks released) (via bm_clock_xxx())
9201 // SS_ABORT - we are told to shutdown (locks releases)
9202
9203 int status;
9204 BUFFER* pbuf = pbuf_guard.get_pbuf();
9205 BUFFER_HEADER *pheader = pbuf->buffer_header;
9206 char *pdata = (char *) (pheader + 1);
9207
9208 /* make sure the buffer never completely full:
9209 * read pointer and write pointer would coincide
9210 * and the code cannot tell if it means the
9211 * buffer is 100% full or 100% empty. It will explode
9212 * or lose events */
9213 requested_space += 100;
9214
9215 if (requested_space >= pheader->size)
9216 return BM_NO_MEMORY;
9217
9218 DWORD time_start = ss_millitime();
9219 DWORD time_end = time_start + timeout_msec;
9220
9221 //DWORD blocking_time = 0;
9222 //int blocking_loops = 0;
9223 int blocking_client_index = -1;
9224 char blocking_client_name[NAME_LENGTH];
9225 blocking_client_name[0] = 0;
9226
9227 while (1) {
9228 while (1) {
9229 /* check if enough space in buffer */
9230
9231 int free = pheader->read_pointer - pheader->write_pointer;
9232 if (free <= 0)
9233 free += pheader->size;
9234
9235 //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);
9236
9237 if (requested_space < free) { /* note the '<' to avoid 100% filling */
9238 //if (blocking_loops) {
9239 // DWORD wait_time = ss_millitime() - blocking_time;
9240 // printf("blocking client \"%s\", time %d ms, loops %d\n", blocking_client_name, wait_time, blocking_loops);
9241 //}
9242
9243 if (pbuf->wait_start_time != 0) {
9244 DWORD now = ss_millitime();
9245 DWORD wait_time = now - pbuf->wait_start_time;
9246 pbuf->time_write_wait += wait_time;
9247 pbuf->wait_start_time = 0;
9248 int iclient = pbuf->wait_client_index;
9249 //printf("bm_wait_for_free_space: wait ended: wait time %d ms, blocking client index %d\n", wait_time, iclient);
9250 if (iclient >= 0 && iclient < MAX_CLIENTS) {
9251 pbuf->client_count_write_wait[iclient] += 1;
9252 pbuf->client_time_write_wait[iclient] += wait_time;
9253 }
9254 }
9255
9256 //if (blocking_loops > 0) {
9257 // 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);
9258 //}
9259
9260 return BM_SUCCESS;
9261 }
9262
9263 if (!bm_validate_rp("bm_wait_for_free_space_locked", pheader, pheader->read_pointer)) {
9264 cm_msg(MERROR, "bm_wait_for_free_space",
9265 "error: buffer \"%s\" is corrupted: read_pointer %d, write_pointer %d, size %d, free %d, waiting for %d bytes: read pointer is invalid",
9266 pheader->name,
9267 pheader->read_pointer,
9268 pheader->write_pointer,
9269 pheader->size,
9270 free,
9271 requested_space);
9272 return BM_CORRUPTED;
9273 }
9274
9275 const EVENT_HEADER *pevent = (const EVENT_HEADER *) (pdata + pheader->read_pointer);
9276 int event_size = pevent->data_size + sizeof(EVENT_HEADER);
9277 int total_size = ALIGN8(event_size);
9278
9279#if 0
9280 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);
9281#endif
9282
9283 if (pevent->data_size <= 0 || total_size <= 0 || total_size > pheader->size) {
9284 cm_msg(MERROR, "bm_wait_for_free_space",
9285 "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",
9286 pheader->name,
9287 pheader->read_pointer,
9288 pheader->write_pointer,
9289 pheader->size,
9290 free,
9291 requested_space,
9292 pevent->data_size,
9293 event_size,
9294 total_size);
9295 return BM_CORRUPTED;
9296 }
9297
9298 int blocking_client = -1;
9299
9300 int i;
9301 for (i = 0; i < pheader->max_client_index; i++) {
9302 BUFFER_CLIENT *pc = pheader->client + i;
9303 if (pc->pid) {
9304 if (pc->read_pointer == pheader->read_pointer) {
9305 /*
9306 First assume that the client with the "minimum" read pointer
9307 is not really blocking due to a GET_ALL request.
9308 */
9309 BOOL blocking = FALSE;
9310 //int blocking_request_id = -1;
9311
9312 int j;
9313 for (j = 0; j < pc->max_request_index; j++) {
9314 const EVENT_REQUEST *prequest = pc->event_request + j;
9315 if (prequest->valid
9316 && bm_match_event(prequest->event_id, prequest->trigger_mask, pevent)) {
9317 if (prequest->sampling_type & GET_ALL) {
9318 blocking = TRUE;
9319 //blocking_request_id = prequest->id;
9320 break;
9321 }
9322 }
9323 }
9324
9325 //printf("client [%s] blocking %d, request %d\n", pc->name, blocking, blocking_request_id);
9326
9327 if (blocking) {
9328 blocking_client = i;
9329 break;
9330 }
9331
9332 pc->read_pointer = bm_incr_rp_no_check(pheader, pc->read_pointer, total_size);
9333 }
9334 }
9335 } /* client loop */
9336
9337 if (blocking_client >= 0) {
9338 blocking_client_index = blocking_client;
9339 mstrlcpy(blocking_client_name, pheader->client[blocking_client].name, sizeof(blocking_client_name));
9340 //if (!blocking_time) {
9341 // blocking_time = ss_millitime();
9342 //}
9343
9344 //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);
9345
9346 // from this "break" we go into timeout check and sleep/wait.
9347 break;
9348 }
9349
9350 /* no blocking clients. move the read pointer and again check for free space */
9351
9352 BOOL moved = bm_update_read_pointer_locked("bm_wait_for_free_space", pheader);
9353
9354 if (!moved) {
9355 cm_msg(MERROR, "bm_wait_for_free_space",
9356 "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",
9357 pheader->name,
9358 pheader->read_pointer,
9359 pheader->write_pointer,
9360 pheader->size,
9361 free,
9362 requested_space);
9363 return BM_CORRUPTED;
9364 }
9365
9366 /* we freed one event, loop back to the check for free space */
9367 }
9368
9369 //blocking_loops++;
9370
9371 /* at least one client is blocking */
9372
9373 BUFFER_CLIENT *pc = bm_get_my_client_locked(pbuf_guard);
9374 pc->write_wait = requested_space;
9375
9376 if (pbuf->wait_start_time == 0) {
9377 pbuf->wait_start_time = ss_millitime();
9378 pbuf->count_write_wait++;
9379 if (requested_space > pbuf->max_requested_space)
9380 pbuf->max_requested_space = requested_space;
9381 pbuf->wait_client_index = blocking_client_index;
9382 }
9383
9384 DWORD now = ss_millitime();
9385
9386 //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);
9387
9388 int sleep_time_msec = 1000;
9389
9390 if (timeout_msec == BM_WAIT) {
9391 // wait forever
9392 } else if (timeout_msec == BM_NO_WAIT) {
9393 // no wait
9394 return BM_ASYNC_RETURN;
9395 } else {
9396 // check timeout
9397 if (now >= time_end) {
9398 // timeout!
9399 return BM_ASYNC_RETURN;
9400 }
9401
9402 sleep_time_msec = time_end - now;
9403
9404 if (sleep_time_msec <= 0) {
9405 sleep_time_msec = 10;
9406 } else if (sleep_time_msec > 1000) {
9407 sleep_time_msec = 1000;
9408 }
9409 }
9410
9412
9413 /* before waiting, unlock everything in the correct order */
9414
9415 pbuf_guard.unlock();
9416
9417 if (unlock_write_cache)
9418 pbuf->write_cache_mutex.unlock();
9419
9420 //printf("bm_wait_for_free_space: blocking client \"%s\"\n", blocking_client_name);
9421
9422#ifdef DEBUG_MSG
9423 cm_msg(MDEBUG, "Send sleep: rp=%d, wp=%d, level=%1.1lf", pheader->read_pointer, pheader->write_pointer, 100 - 100.0 * size / pheader->size);
9424#endif
9425
9427 //int idx = bm_validate_client_index_locked(pbuf, FALSE);
9428 //if (idx >= 0)
9429 // pheader->client[idx].write_wait = requested_space;
9430
9431 //bm_cleanup("bm_wait_for_free_space", ss_millitime(), FALSE);
9432
9433 status = ss_suspend(sleep_time_msec, MSG_BM);
9434
9435 /* we are told to shutdown */
9436 if (status == SS_ABORT) {
9437 // NB: buffer is locked!
9438 return SS_ABORT;
9439 }
9440
9441 /* make sure we do sleep in this loop:
9442 * if we are the mserver receiving data on the event
9443 * socket and the data buffer is full, ss_suspend() will
9444 * never sleep: it will detect data on the event channel,
9445 * call rpc_server_receive() (recursively, we already *are* in
9446 * rpc_server_receive()) and return without sleeping. Result
9447 * is a busy loop waiting for free space in data buffer */
9448
9449 /* update May 2021: ss_suspend(MSG_BM) no longer looks at
9450 * the event socket, and should sleep now, so this sleep below
9451 * maybe is not needed now. but for safety, I keep it. K.O. */
9452
9453 if (status != SS_TIMEOUT) {
9454 //printf("ss_suspend: status %d\n", status);
9455 ss_sleep(1);
9456 }
9457
9458 /* we may be stuck in this loop for an arbitrary long time,
9459 * depending on how other buffer clients read the accumulated data
9460 * so we should update all the timeouts & etc. K.O. */
9461
9463
9464 /* lock things again in the correct order */
9465
9466 if (unlock_write_cache) {
9468
9469 if (status != BM_SUCCESS) {
9470 // bail out with all locks released
9471 return status;
9472 }
9473 }
9474
9475 if (!pbuf_guard.relock()) {
9476 if (unlock_write_cache) {
9477 pbuf->write_cache_mutex.unlock();
9478 }
9479
9480 // bail out with all locks released
9481 return pbuf_guard.get_status();
9482 }
9483
9484 /* revalidate the client index: we could have been removed from the buffer while sleeping */
9485 pc = bm_get_my_client_locked(pbuf_guard);
9486
9487 pc->write_wait = 0;
9488
9490 //idx = bm_validate_client_index_locked(pbuf, FALSE);
9491 //if (idx >= 0)
9492 // pheader->client[idx].write_wait = 0;
9493 //else {
9494 // cm_msg(MERROR, "bm_wait_for_free_space", "our client index is no longer valid, exiting...");
9495 // status = SS_ABORT;
9496 //}
9497
9498#ifdef DEBUG_MSG
9499 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);
9500#endif
9501
9502 }
9503}
int get_status() const
Definition midas.cxx:3248
static BOOL bm_update_read_pointer_locked(const char *caller_name, BUFFER_HEADER *pheader)
Definition midas.cxx:8833
INT cm_periodic_tasks()
Definition midas.cxx:5653
#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 9505 of file midas.cxx.

9506{
9507 BUFFER* pbuf = pbuf_guard.get_pbuf();
9508 BUFFER_HEADER* pheader = pbuf->buffer_header;
9509
9510 //printf("bm_wait_for_more_events_locked: [%s] timeout %d\n", pheader->name, timeout_msec);
9511
9512 if (pc->read_pointer != pheader->write_pointer) {
9513 // buffer has data
9514 return BM_SUCCESS;
9515 }
9516
9517 if (timeout_msec == BM_NO_WAIT) {
9518 /* event buffer is empty and we are told to not wait */
9519 if (!pc->read_wait) {
9520 //printf("bm_wait_for_more_events: buffer [%s] client [%s] set read_wait in BM_NO_WAIT!\n", pheader->name, pc->name);
9521 pc->read_wait = TRUE;
9522 }
9523 return BM_ASYNC_RETURN;
9524 }
9525
9526 DWORD time_start = ss_millitime();
9527 DWORD time_wait = time_start + timeout_msec;
9528 DWORD sleep_time = 1000;
9529 if (timeout_msec == BM_NO_WAIT) {
9530 // default sleep time
9531 } else if (timeout_msec == BM_WAIT) {
9532 // default sleep time
9533 } else {
9534 if (sleep_time > (DWORD)timeout_msec)
9535 sleep_time = timeout_msec;
9536 }
9537
9538 //printf("time start 0x%08x, end 0x%08x, sleep %d\n", time_start, time_wait, sleep_time);
9539
9540 while (pc->read_pointer == pheader->write_pointer) {
9541 /* wait until there is data in the buffer (write pointer moves) */
9542
9543 if (!pc->read_wait) {
9544 //printf("bm_wait_for_more_events: buffer [%s] client [%s] set read_wait!\n", pheader->name, pc->name);
9545 pc->read_wait = TRUE;
9546 }
9547
9549
9551
9552 // NB: locking order is: 1st read cache lock, 2nd buffer lock, unlock in reverse order
9553
9554 pbuf_guard.unlock();
9555
9556 if (unlock_read_cache)
9557 pbuf->read_cache_mutex.unlock();
9558
9559 int status = ss_suspend(sleep_time, MSG_BM);
9560
9561 if (timeout_msec == BM_NO_WAIT) {
9562 // return immediately
9563 } else if (timeout_msec == BM_WAIT) {
9564 // wait forever
9565 } else {
9566 DWORD now = ss_millitime();
9567 //printf("check timeout: now 0x%08x, end 0x%08x, diff %d\n", now, time_wait, time_wait - now);
9568 if (now >= time_wait) {
9569 timeout_msec = BM_NO_WAIT; // cause immediate return
9570 } else {
9571 sleep_time = time_wait - now;
9572 if (sleep_time > 1000)
9573 sleep_time = 1000;
9574 //printf("time start 0x%08x, now 0x%08x, end 0x%08x, sleep %d\n", time_start, now, time_wait, sleep_time);
9575 }
9576 }
9577
9578 // NB: locking order is: 1st read cache lock, 2nd buffer lock, unlock in reverse order
9579
9580 if (unlock_read_cache) {
9582 if (status != BM_SUCCESS) {
9583 // bail out with all locks released
9584 return status;
9585 }
9586 }
9587
9588 if (!pbuf_guard.relock()) {
9589 if (unlock_read_cache) {
9590 pbuf->read_cache_mutex.unlock();
9591 }
9592 // bail out with all locks released
9593 return pbuf_guard.get_status();
9594 }
9595
9596 /* need to revalidate our BUFFER_CLIENT after releasing the buffer lock
9597 * because we may have been removed from the buffer by bm_cleanup() & co
9598 * due to a timeout or whatever. */
9599 pc = bm_get_my_client_locked(pbuf_guard);
9600
9601 /* return if TCP connection broken */
9602 if (status == SS_ABORT)
9603 return SS_ABORT;
9604
9605 if (timeout_msec == BM_NO_WAIT)
9606 return BM_ASYNC_RETURN;
9607 }
9608
9609 if (pc->read_wait) {
9610 //printf("bm_wait_for_more_events: buffer [%s] client [%s] clear read_wait!\n", pheader->name, pc->name);
9611 pc->read_wait = FALSE;
9612 }
9613
9614 return BM_SUCCESS;
9615}
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 8900 of file midas.cxx.

8900 {
8901 int i;
8902 int have_get_all_requests = 0;
8903
8904 for (i = 0; i < pc->max_request_index; i++)
8905 if (pc->event_request[i].valid)
8906 have_get_all_requests |= (pc->event_request[i].sampling_type == GET_ALL);
8907
8908 /* only GET_ALL requests actually free space in the event buffer */
8909 if (!have_get_all_requests)
8910 return;
8911
8912 /*
8913 If read pointer has been changed, it may have freed up some space
8914 for waiting producers. So check if free space is now more than 50%
8915 of the buffer size and wake waiting producers.
8916 */
8917
8918 int free_space = pc->read_pointer - pheader->write_pointer;
8919 if (free_space <= 0)
8920 free_space += pheader->size;
8921
8922 if (free_space >= pheader->size * 0.5) {
8923 for (i = 0; i < pheader->max_client_index; i++) {
8924 const BUFFER_CLIENT *pc = pheader->client + i;
8925 if (pc->pid && pc->write_wait) {
8926 BOOL send_wakeup = (pc->write_wait < free_space);
8927 //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);
8928 if (send_wakeup) {
8929 ss_resume(pc->port, "B ");
8930 }
8931 }
8932 }
8933 }
8934}
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 6651 of file midas.cxx.

6652{
6653 //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);
6654
6655 bm_lock_buffer_guard pbuf_guard(pbuf);
6656
6657 if (!pbuf_guard.is_locked())
6658 return;
6659
6660 if (!force) {
6661 if (pbuf->count_lock == pbuf->last_count_lock) {
6662 return;
6663 }
6664 }
6665
6666 std::string buffer_name = pbuf->buffer_name;
6667 std::string client_name = pbuf->client_name;
6668
6669 if ((strlen(buffer_name.c_str()) < 1) || (strlen(client_name.c_str()) < 1)) {
6670 // do not call cm_msg() while holding buffer lock, if we are SYSMSG, we will deadlock. K.O.
6671 pbuf_guard.unlock(); // unlock before cm_msg()
6672 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());
6673 return;
6674 }
6675
6676 pbuf->last_count_lock = pbuf->count_lock;
6677
6678 BUFFER_INFO xbuf(pbuf);
6679 BUFFER_HEADER xheader = *pbuf->buffer_header;
6680 int client_index = pbuf->client_index;
6681
6682 pbuf_guard.unlock();
6683
6684 bm_write_buffer_statistics_to_odb_copy(hDB, buffer_name.c_str(), client_name.c_str(), client_index, &xbuf, &xheader);
6685}
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:6529
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 6529 of file midas.cxx.

6530{
6531 int status;
6532
6533 DWORD now = ss_millitime();
6534
6535 HNDLE hKey;
6536 status = db_find_key(hDB, 0, "/System/Buffers", &hKey);
6537 if (status != DB_SUCCESS) {
6538 db_create_key(hDB, 0, "/System/Buffers", TID_KEY);
6539 status = db_find_key(hDB, 0, "/System/Buffers", &hKey);
6540 if (status != DB_SUCCESS)
6541 return;
6542 }
6543
6544 HNDLE hKeyBuffer;
6545 status = db_find_key(hDB, hKey, buffer_name, &hKeyBuffer);
6546 if (status != DB_SUCCESS) {
6548 status = db_find_key(hDB, hKey, buffer_name, &hKeyBuffer);
6549 if (status != DB_SUCCESS)
6550 return;
6551 }
6552
6553 double buf_size = pheader->size;
6554 double buf_rptr = pheader->read_pointer;
6555 double buf_wptr = pheader->write_pointer;
6556
6557 double buf_fill = 0;
6558 double buf_cptr = 0;
6559 double buf_cused = 0;
6560 double buf_cused_pct = 0;
6561
6562 if (client_index >= 0 && client_index <= pheader->max_client_index) {
6563 buf_cptr = pheader->client[client_index].read_pointer;
6564
6565 if (buf_wptr == buf_cptr) {
6566 buf_cused = 0;
6567 } else if (buf_wptr > buf_cptr) {
6568 buf_cused = buf_wptr - buf_cptr;
6569 } else {
6570 buf_cused = (buf_size - buf_cptr) + buf_wptr;
6571 }
6572
6573 buf_cused_pct = buf_cused / buf_size * 100.0;
6574
6575 // we cannot write buf_cused and buf_cused_pct into the buffer statistics
6576 // because some other GET_ALL client may have different buf_cused & etc,
6577 // so they must be written into the per-client statistics
6578 // and the web page should look at all the GET_ALL clients and used
6579 // the biggest buf_cused as the whole-buffer "bytes used" value.
6580 }
6581
6582 if (buf_wptr == buf_rptr) {
6583 buf_fill = 0;
6584 } else if (buf_wptr > buf_rptr) {
6585 buf_fill = buf_wptr - buf_rptr;
6586 } else {
6587 buf_fill = (buf_size - buf_rptr) + buf_wptr;
6588 }
6589
6590 double buf_fill_pct = buf_fill / buf_size * 100.0;
6591
6592 db_set_value(hDB, hKeyBuffer, "Size", &buf_size, sizeof(double), 1, TID_DOUBLE);
6593 db_set_value(hDB, hKeyBuffer, "Write pointer", &buf_wptr, sizeof(double), 1, TID_DOUBLE);
6594 db_set_value(hDB, hKeyBuffer, "Read pointer", &buf_rptr, sizeof(double), 1, TID_DOUBLE);
6595 db_set_value(hDB, hKeyBuffer, "Filled", &buf_fill, sizeof(double), 1, TID_DOUBLE);
6596 db_set_value(hDB, hKeyBuffer, "Filled pct", &buf_fill_pct, sizeof(double), 1, TID_DOUBLE);
6597
6598 status = db_find_key(hDB, hKeyBuffer, "Clients", &hKey);
6599 if (status != DB_SUCCESS) {
6600 db_create_key(hDB, hKeyBuffer, "Clients", TID_KEY);
6601 status = db_find_key(hDB, hKeyBuffer, "Clients", &hKey);
6602 if (status != DB_SUCCESS)
6603 return;
6604 }
6605
6606 HNDLE hKeyClient;
6607 status = db_find_key(hDB, hKey, client_name, &hKeyClient);
6608 if (status != DB_SUCCESS) {
6609 db_create_key(hDB, hKey, client_name, TID_KEY);
6610 status = db_find_key(hDB, hKey, client_name, &hKeyClient);
6611 if (status != DB_SUCCESS)
6612 return;
6613 }
6614
6615 db_set_value(hDB, hKeyClient, "count_lock", &pbuf->count_lock, sizeof(int), 1, TID_INT32);
6616 db_set_value(hDB, hKeyClient, "count_sent", &pbuf->count_sent, sizeof(int), 1, TID_INT32);
6617 db_set_value(hDB, hKeyClient, "bytes_sent", &pbuf->bytes_sent, sizeof(double), 1, TID_DOUBLE);
6618 db_set_value(hDB, hKeyClient, "count_write_wait", &pbuf->count_write_wait, sizeof(int), 1, TID_INT32);
6619 db_set_value(hDB, hKeyClient, "time_write_wait", &pbuf->time_write_wait, sizeof(DWORD), 1, TID_UINT32);
6620 db_set_value(hDB, hKeyClient, "max_bytes_write_wait", &pbuf->max_requested_space, sizeof(INT), 1, TID_INT32);
6621 db_set_value(hDB, hKeyClient, "count_read", &pbuf->count_read, sizeof(int), 1, TID_INT32);
6622 db_set_value(hDB, hKeyClient, "bytes_read", &pbuf->bytes_read, sizeof(double), 1, TID_DOUBLE);
6623 db_set_value(hDB, hKeyClient, "get_all_flag", &pbuf->get_all_flag, sizeof(BOOL), 1, TID_BOOL);
6624 db_set_value(hDB, hKeyClient, "read_pointer", &buf_cptr, sizeof(double), 1, TID_DOUBLE);
6625 db_set_value(hDB, hKeyClient, "bytes_used", &buf_cused, sizeof(double), 1, TID_DOUBLE);
6626 db_set_value(hDB, hKeyClient, "pct_used", &buf_cused_pct, sizeof(double), 1, TID_DOUBLE);
6627
6628 for (int i = 0; i < MAX_CLIENTS; i++) {
6629 if (!pbuf->client_count_write_wait[i])
6630 continue;
6631
6632 if (pheader->client[i].pid == 0)
6633 continue;
6634
6635 if (pheader->client[i].name[0] == 0)
6636 continue;
6637
6638 char str[100 + NAME_LENGTH];
6639
6640 sprintf(str, "writes_blocked_by/%s/count_write_wait", pheader->client[i].name);
6641 db_set_value(hDB, hKeyClient, str, &pbuf->client_count_write_wait[i], sizeof(int), 1, TID_INT32);
6642
6643 sprintf(str, "writes_blocked_by/%s/time_write_wait", pheader->client[i].name);
6644 db_set_value(hDB, hKeyClient, str, &pbuf->client_time_write_wait[i], sizeof(DWORD), 1, TID_UINT32);
6645 }
6646
6647 db_set_value(hDB, hKeyBuffer, "Last updated", &now, sizeof(DWORD), 1, TID_UINT32);
6648 db_set_value(hDB, hKeyClient, "last_updated", &now, sizeof(DWORD), 1, TID_UINT32);
6649}
#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:6492
BOOL get_all_flag
Definition midas.cxx:6488
int count_lock
Definition midas.cxx:6491
int count_write_wait
Definition midas.cxx:6494
double bytes_read
Definition midas.cxx:6501
int client_count_write_wait[MAX_CLIENTS]
Definition midas.cxx:6502
DWORD time_write_wait
Definition midas.cxx:6495
int count_read
Definition midas.cxx:6500
double bytes_sent
Definition midas.cxx:6493
DWORD client_time_write_wait[MAX_CLIENTS]
Definition midas.cxx:6503
int max_requested_space
Definition midas.cxx:6499
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 7354 of file midas.cxx.

7354 {
7355#ifdef LOCAL_ROUTINES
7356 {
7357 int status;
7358 HNDLE hDB;
7359
7361
7362 if (status != CM_SUCCESS) {
7363 //printf("bm_write_statistics_to_odb: cannot get ODB handle!\n");
7364 return BM_SUCCESS;
7365 }
7366
7367 std::vector<BUFFER*> mybuffers;
7368
7369 gBuffersMutex.lock();
7370 mybuffers = gBuffers;
7371 gBuffersMutex.unlock();
7372
7373 for (BUFFER* pbuf : mybuffers) {
7374 if (!pbuf || !pbuf->attached)
7375 continue;
7377 }
7378 }
7379#endif /* LOCAL_ROUTINES */
7380
7381 return BM_SUCCESS;
7382}
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 9617 of file midas.cxx.

9618{
9619 char *pdata = (char *) (pheader + 1);
9620
9621 //int old_write_pointer = pheader->write_pointer;
9622
9623 /* new event fits into the remaining space? */
9624 if ((size_t)pheader->write_pointer + total_size <= (size_t)pheader->size) {
9625 //memcpy(pdata + pheader->write_pointer, pevent, event_size);
9626 char* wptr = pdata + pheader->write_pointer;
9627 for (int i=0; i<sg_n; i++) {
9628 //printf("memcpy %p+%d\n", sg_ptr[i], (int)sg_len[i]);
9629 memcpy(wptr, sg_ptr[i], sg_len[i]);
9630 wptr += sg_len[i];
9631 }
9632 pheader->write_pointer = pheader->write_pointer + total_size;
9633 assert(pheader->write_pointer <= pheader->size);
9634 /* remaining space is smaller than size of an event header? */
9635 if ((pheader->write_pointer + (int) sizeof(EVENT_HEADER)) > pheader->size) {
9636 // note: ">" here to match "bm_incr_rp". If remaining space is exactly
9637 // equal to the event header size, we will write the next event header here,
9638 // then wrap the pointer and write the event data at the beginning of the buffer.
9639 //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);
9640 pheader->write_pointer = 0;
9641 }
9642 } else {
9643 /* split event */
9644 size_t size = pheader->size - pheader->write_pointer;
9645
9646 //printf("split: wp %d, size %d, avail %d\n", pheader->write_pointer, pheader->size, size);
9647
9648 //memcpy(pdata + pheader->write_pointer, pevent, size);
9649 //memcpy(pdata, ((const char *) pevent) + size, event_size - size);
9650
9651 char* wptr = pdata + pheader->write_pointer;
9652 size_t count = 0;
9653
9654 // copy first part
9655
9656 int i = 0;
9657 for (; i<sg_n; i++) {
9658 if (count + sg_len[i] > size)
9659 break;
9660 memcpy(wptr, sg_ptr[i], sg_len[i]);
9661 wptr += sg_len[i];
9662 count += sg_len[i];
9663 }
9664
9665 //printf("wptr %d, count %d\n", wptr-pdata, count);
9666
9667 // split segment
9668
9669 size_t first = size - count;
9670 size_t second = sg_len[i] - first;
9671 assert(first + second == sg_len[i]);
9672 assert(count + first == size);
9673
9674 //printf("first %d, second %d\n", first, second);
9675
9676 memcpy(wptr, sg_ptr[i], first);
9677 wptr = pdata + 0;
9678 count += first;
9679 memcpy(wptr, sg_ptr[i] + first, second);
9680 wptr += second;
9681 count += second;
9682 i++;
9683
9684 // copy remaining
9685
9686 for (; i<sg_n; i++) {
9687 memcpy(wptr, sg_ptr[i], sg_len[i]);
9688 wptr += sg_len[i];
9689 count += sg_len[i];
9690 }
9691
9692 //printf("wptr %d, count %d\n", wptr-pdata, count);
9693
9694 //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);
9695
9696 pheader->write_pointer = total_size - size;
9697 }
9698
9699 //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);
9700}
Here is the caller graph for this function:

Variable Documentation

◆ _bm_lock_timeout

int _bm_lock_timeout = 5 * 60 * 1000
static

Definition at line 5991 of file midas.cxx.

◆ _bm_max_event_size

DWORD _bm_max_event_size = 0
static

Definition at line 5986 of file midas.cxx.

◆ _bm_mutex_timeout_sec

double _bm_mutex_timeout_sec = _bm_lock_timeout/1000 + 15.000
static

Definition at line 5992 of file midas.cxx.

◆ defrag_buffer

EVENT_DEFRAG_BUFFER defrag_buffer[MAX_DEFRAG_EVENTS]
static

Definition at line 11522 of file midas.cxx.