Belle II Software development
HistoServer2.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include <daq/dqm/HistoServer2.h>
9
10#include <framework/pcore/MsgHandler.h>
11#include <ctime>
12#include <arpa/inet.h>
13
14using namespace Belle2;
15using namespace std;
16
17// Constructor / Destructor
18HistoServer2::HistoServer2(int port, const string& filename)
19{
20 m_port = port;
21 m_force_exit = 0;
22 m_filename = filename;
23}
24
25HistoServer2::~HistoServer2()
26{
27 delete m_sock;
28}
29
30// Initialize socket
31
32int HistoServer2::init()
33{
34 m_sock = new EvtSocketRecv(m_port, false);
35 m_man = new EvtSocketManager(m_sock);
36 m_hman = new HistoManager2(m_filename);
37 return 0;
38
39}
40// Server function to collect histograms
41
42int HistoServer2::server()
43{
44 SocketIO sio;
45 MsgHandler msghdl(0);
46 char mbstr[100];
47 time_t now;
48 char* buffer = new char[c_maxBufSize];
49 // vector<int> recvsock;
50 int loop_counter = 0;
51 bool updated = false;
53 while (m_force_exit == 0) {
54 fflush(stdout);
55 int exam_stat = m_man->examine();
56 if (exam_stat == 0) {
57 } else if (exam_stat == 1) { //
58 // printf ( "Histo data ready on socket\n" );
59 vector<int>& recvsock = m_man->connected_socket_list();
60 for (vector<int>::iterator it = recvsock.begin();
61 it != recvsock.end(); ++it) {
62 int fd = *it;
63 if (m_man->connected(fd)) {
64 struct sockaddr_in isa;
65 socklen_t isize = sizeof(isa);
66 getpeername(fd, (struct sockaddr*)&isa, &isize);
67 char address[INET_ADDRSTRLEN];
68 strcpy(address, inet_ntoa(isa.sin_addr));
69 char* ptr = strrchr(address, '.');
70 int nr = -1;
71 if (ptr) {
72 nr = atoi(ptr + 1);
73 }
74 m_unit_last_conn_time[nr] = now;
75
76 int is = sio.get(fd, buffer, c_maxBufSize);
77 if (is <= 0) {
78 now = time(0);
79 strftime(mbstr, sizeof(mbstr), "%F %T", localtime(&now));
80 printf("[%s] HistoServer2: fd %d / %s disconnected\n", mbstr, fd, address);
81 m_man->remove(fd);
82 m_units_connected[address] = std::pair(nr, false);
83 break;
84 }
85 m_units_connected[address] = std::pair(nr, true);
86 // printf ( "EvtMessage received : size = %d from fd=%d\n", is, fd );
87
88 EvtMessage* hmsg = new EvtMessage(buffer);
89 vector<TObject*> objlist;
90 vector<string> strlist;
91 msghdl.decode_msg(hmsg, objlist, strlist);
92 int nobjs = (hmsg->header())->reserved[1];
93 // string subdir = "ROOT";
94 string subdir = "";
95 now = time(0);
96 strftime(mbstr, sizeof(mbstr), "%F %T", localtime(&now));
97 m_unit_last_packet_time[nr] = now;
98 printf("[%s] HistoServer2 : received nobjs = %d from %s\n", mbstr, nobjs, address);
99 if (nobjs > 0) m_unit_last_content_time[nr] = now;
100 for (int i = 0; i < nobjs; i++) {
101 // printf ( "Object : %s received, class = %s\n", (strlist.at(i)).c_str(),
102 // (objlist.at(i))->ClassName() );
103 string objname = strlist.at(i);
104 if (objname == string("DQMRC:CLEAR")) {
105 m_hman->clear();
106 m_hman->merge();
107 updated = false; // have merged, thus reset updated
108 m_last_merge_time = time(0);
109 strftime(mbstr, sizeof(mbstr), "%F %T", localtime(&m_last_merge_time));
110 printf("[%s] HistoServer2: CLEAR\n", mbstr);
111 continue;
112 }
113 if (objname == string("DQMRC:MERGE")) {
114 m_hman->merge();
115 updated = false; // have merged, thus reset updated
116 m_last_merge_time = time(0);
117 strftime(mbstr, sizeof(mbstr), "%F %T", localtime(&m_last_merge_time));
118 printf("[%s] HistoServer2: MERGE\n", mbstr);
119 continue;
120 }
121 auto lpos = objname.find("DQMRC:SAVE:");
122 if (lpos != string::npos) {
123 auto filename = objname.substr(11);
124 m_hman->filedump(filename);
125 continue;
126 }
127 lpos = objname.find("SUBDIR:");
128 if (lpos != string::npos) {
129 subdir = objname.substr(7);
130 if (subdir == "EXIT") subdir = "";
131 // printf("HistoServer2 : subdirectory set to %s (%s)\n", subdir.c_str(), objname.c_str());
132 // no update to histograms ...
133 } else {
134 m_hman->update(subdir, strlist.at(i), fd, (TH1*)objlist.at(i));
135 updated = true; // histograms have been updated
136 }
137 }
138 }
139 }
140 }
141 usleep(1000);
142 loop_counter++;
143 if (loop_counter % c_mergeIntervall == 0) {
144 if (updated) {
145 m_last_merge_time = time(0);
146 strftime(mbstr, sizeof(mbstr), "%F %T", localtime(&m_last_merge_time));
147 printf("[%s] HistoServer2: merging histograms\n", mbstr);
148 m_hman->merge();
149 updated = false; // have merged, thus reset updated
150 }
151 write_state();
152 }
153 }
154 return 0;
155}
156
158{
159 char mbstr[100];
160 char mbstr2[100];
161 char mbstr3[100];
162 std::string name = "/tmp/dqm_hserver_state_" + m_filename;
163 FILE* fh = fopen(name.c_str(), "wt+");
164 if (fh) {
165 time_t now = time(0);
166 strftime(mbstr, sizeof(mbstr), "%F %T", localtime(&now));
167 strftime(mbstr2, sizeof(mbstr2), "%F %T", localtime(&m_last_merge_time));
168 fprintf(fh, "%s,%s,%s\n", m_filename.c_str(), mbstr, mbstr2);
169
170 for (auto& it : m_units_connected) {
171 int nr = it.second.first;
172 int con = it.second.second;
173 strftime(mbstr, sizeof(mbstr), "%F %T", localtime(&m_unit_last_conn_time[nr]));
174 strftime(mbstr2, sizeof(mbstr2), "%F %T", localtime(&m_unit_last_packet_time[nr]));
175 strftime(mbstr3, sizeof(mbstr3), "%F %T", localtime(&m_unit_last_content_time[nr]));
176 if (it.first == "127.0.0.1") {
177 fprintf(fh, "RUNCONTROL,");
178 } else {
179 if (nr >= 0 and nr < 20) {
180 fprintf(fh, "HLT%d,", nr);
181 } else if (nr > 100 and nr < 110) {
182 fprintf(fh, "ERECO%d,", nr - 100);
183 } else {
184 fprintf(fh, "UNKNOWN,");
185 }
186 }
187 fprintf(fh, "%s,%d,%s,%s,%s\n", it.first.c_str(), con, mbstr, mbstr2, mbstr3);
188 }
189 fclose(fh);
190 }
191}
Class to manage streamed object.
Definition: EvtMessage.h:59
EvtHeader * header()
Get pointer to EvtHeader.
Definition: EvtMessage.cc:161
std::map< std::string, std::pair< int, bool > > m_units_connected
connection IP, state and last update time
Definition: HistoServer2.h:52
void write_state(void)
Write connection state to a file.
A class to encode/decode an EvtMessage.
Definition: MsgHandler.h:103
Abstract base class for different kinds of events.
STL namespace.