AlcapDAQ  1
rpc_slave.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 
4 #include <unistd.h>
5 #include <sys/io.h>
6 #include <sys/time.h>
7 
8 #include "midas.h"
9 
10 #include "crate.h"
11 #include "diag.h"
12 #include "odb_wrapper.h"
13 
14 #include "rpc_mucap.h"
15 
16 INT rpc_end_of_cycle(INT index, void *prpc_param[]);
17 INT rpc_slave_init();
18 INT rpc_slave_bor();
19 INT rpc_slave_eor();
23 INT rpc_slave_read(char *pevent);
24 
26 
27 static HNDLE rpc_conn_master_crate;
28 static BOOL enable_rpc_slave;
29 
30 static BOOL event_ended = FALSE;
31 static INT last_cycle = 0;
32 static INT last_event_number = 0;
33 static INT sent_stop_request = -1;
34 
36  rpc_slave_init, // init
37  NULL, // exit
38  NULL, // pre_bor
39  rpc_slave_bor, // bor
40  rpc_slave_eor, // eor
41  rpc_slave_poll_live, // poll_live
42  rpc_slave_poll_dead, // poll_dead
43  NULL, // start_block
44  rpc_slave_stop_block, // stop_block
45  rpc_slave_read, // read
46 };
47 
48 /* ********************************************************************* */
49 INT rpc_end_of_cycle(INT index, void *prpc_param[])
50 {
51  INT cycle_number = CINT(0);
52  INT event_number = CINT(1);
53 
54  diag_print(2, "Cycle ended: RAM %d, event %d\n", cycle_number, event_number);
55 
56  // first send out "fake" zero-length events for those cycles
57  // where we didn't participate
58  for(INT fake_evnum=last_event_number+1; fake_evnum < event_number;
59  fake_evnum++)
60  {
61  diag_print(2, "Sending fake catch-up event for %d\n", fake_evnum);
62  char fake_event[sizeof(EVENT_HEADER) + sizeof(BANK_HEADER)];
63  char *pevent = fake_event + sizeof(EVENT_HEADER);
64 
65  rpc_flush_event();
66  bk_init32(pevent);
67  bm_compose_event((EVENT_HEADER *) fake_event, equipment[0].info.event_id, 0,
68  bk_size(pevent), fake_evnum);
69  bm_send_event(equipment[0].buffer_handle, fake_event,
70  sizeof(fake_event), SYNC);
71  bm_flush_cache(equipment[0].buffer_handle, SYNC);
72  }
73 
74  event_ended = true;
75  last_cycle = cycle_number;
77 
78  return SUCCESS;
79 }
80 
81 /* ********************************************************************* */
83 {
84  // register the RPC function that we provide
85  rpc_register_functions(rpc_list_mucap, NULL);
86  rpc_register_function(RPC_END_OF_CYCLE, rpc_end_of_cycle);
87 
88  return SUCCESS;
89 }
90 
91 /* ********************************************************************* */
93 {
96  sent_stop_request = -1;
97  last_cycle = 0;
98 
99  // find the master crate
100  int master_crate = -1;
101  for(int i = 0; i < MAX_CRATES; i++) {
102  if(odb_find_key("/Equipment/Crate %d", i) != NULL) {
103  BOOL master = odb_get_bool("/Equipment/Crate %d/Settings/Master", i);
104  if(master) master_crate = i;
105  }
106  }
107 
108  // maybe we're the master...in that case, disable slave function
109  if(master_crate == crate_number) {
111  diag_print(1, "Disabling RPC slave function\n");
112  return SUCCESS;
113  } else {
115  diag_print(1, "Enabling RPC slave function\n");
116  }
117 
118  // return error if unable to find the master crate
119  if(master_crate < 0) {
120  diag_print(0, "Unable to locate master crate\n");
121  return FE_ERR_HW;
122  }
123  diag_print(1, "Found master crate %d\n", master_crate);
124 
125  // establish RPC connections to the master crate
126  char master_crate_label[10];
127  sprintf(master_crate_label, "Crate %d", master_crate);
128 
129  cm_connect_client(master_crate_label, &rpc_conn_master_crate);
130  rpc_set_option(rpc_conn_master_crate, RPC_OTRANSPORT, RPC_FTCP);
131  rpc_set_option(rpc_conn_master_crate, RPC_NODELAY, TRUE);
132 
134 
135  return SUCCESS;
136 }
137 
138 /* ********************************************************************* */
140 {
141  if(enable_rpc_slave) {
142  cm_disconnect_client(rpc_conn_master_crate, 0);
143  }
144  return SUCCESS;
145 }
146 
147 /* ********************************************************************* */
149 {
150  if(!enable_rpc_slave) {
151  return SUCCESS;
152  }
153 
154  // Yield to receive any pending RPCs
155  cm_yield(0);
156 
157  // Have we received an end-of-event notice?
158  if(event_ended) {
159  event_ended = FALSE;
160  diag_print(2, "event ended\n");
161  return FE_END_BLOCK;
162  } else {
163  return SUCCESS;
164  }
165 }
166 
167 /* ********************************************************************* */
169 {
170  if(!enable_rpc_slave) {
171  return SUCCESS;
172  }
173 
174  return FE_NEED_START;
175 }
176 
177 /* ********************************************************************* */
179 {
180  if(!enable_rpc_slave) {
181  return SUCCESS;
182  }
183 
185 
186  // Send a request to the master crate for the block to end.
187  if(sent_stop_request < event_number) {
189  event_number);
191  }
192 
193  return SUCCESS;
194 }
195 
196 /* ********************************************************************* */
197 INT rpc_slave_read(char *pevent)
198 {
199  if(!enable_rpc_slave) {
200  return SUCCESS;
201  }
202 
203  // Fill in event number
204  (((EVENT_HEADER *)pevent)-1)->serial_number = last_event_number;
205 
206  // Announce that we're ready for the next cycle
207 
209 
210  return SUCCESS;
211 }
212 
213 /* ********************************************************************* */
215 {
216  // Send "ready to go"
217  struct timeval tv1, tv2;
218  gettimeofday(&tv1, NULL);
220  gettimeofday(&tv2, NULL);
221 
222  diag_print(2, "Waited %f microseconds for RPC_READY_FOR_CYCLE.\n",
223  (tv2.tv_sec-tv1.tv_sec)*1e6 + (tv2.tv_usec-tv1.tv_usec));
224 
225  return SUCCESS;
226 }
227 
228 /* ********************************************************************* */