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 /* ********************************************************************* */
82 INT rpc_slave_init()
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 /* ********************************************************************* */
92 INT rpc_slave_bor()
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  printf("looking for master crate ...\n");
120  if(master_crate < 0) {
121  printf("no master found\n");
122  diag_print(0, "Unable to locate master crate\n");
123  return FE_ERR_HW;
124  }
125  diag_print(1, "Found master crate %d\n", master_crate);
126  printf("Master :%d\n", master_crate);
127 
128  // establish RPC connections to the master crate
129  char master_crate_label[10];
130  sprintf(master_crate_label, "Crate %d", master_crate);
131 
132  cm_connect_client(master_crate_label, &rpc_conn_master_crate);
133  rpc_set_option(rpc_conn_master_crate, RPC_OTRANSPORT, RPC_FTCP);
134  rpc_set_option(rpc_conn_master_crate, RPC_NODELAY, TRUE);
135 
137 
138  return SUCCESS;
139 }
140 
141 /* ********************************************************************* */
142 INT rpc_slave_eor()
143 {
144  if(enable_rpc_slave) {
145  cm_disconnect_client(rpc_conn_master_crate, 0);
146  }
147  return SUCCESS;
148 }
149 
150 /* ********************************************************************* */
152 {
153  if(!enable_rpc_slave) {
154  return SUCCESS;
155  }
156 
157  // Yield to receive any pending RPCs
158  cm_yield(1000);
159 
160  // Have we received an end-of-event notice?
161  if(event_ended) {
162  event_ended = FALSE;
163  diag_print(2, "event ended\n");
164  return FE_END_BLOCK;
165  } else {
166  return SUCCESS;
167  }
168 }
169 
170 /* ********************************************************************* */
172 {
173  if(!enable_rpc_slave) {
174  return SUCCESS;
175  }
176 
177  return FE_NEED_START;
178 }
179 
180 /* ********************************************************************* */
182 {
183  if(!enable_rpc_slave) {
184  return SUCCESS;
185  }
186 
187  int event_number = last_event_number + 1;
188 
189  // Send a request to the master crate for the block to end.
190  if(sent_stop_request < event_number) {
192  event_number);
194  }
195 
196  return SUCCESS;
197 }
198 
199 /* ********************************************************************* */
200 INT rpc_slave_read(char *pevent)
201 {
202  if(!enable_rpc_slave) {
203  return SUCCESS;
204  }
205 
206  // Fill in event number
207  (((EVENT_HEADER *)pevent)-1)->serial_number = last_event_number;
208 
209  // Announce that we're ready for the next cycle
210 
212 
213  return SUCCESS;
214 }
215 
216 /* ********************************************************************* */
218 {
219  // Send "ready to go"
220  struct timeval tv1, tv2;
221  gettimeofday(&tv1, NULL);
223  gettimeofday(&tv2, NULL);
224 
225  diag_print(2, "Waited %f microseconds for RPC_READY_FOR_CYCLE.\n",
226  (tv2.tv_sec-tv1.tv_sec)*1e6 + (tv2.tv_usec-tv1.tv_usec));
227 
228  return SUCCESS;
229 }
230 
231 /* ********************************************************************* */