Skip to content

Commit 0e23762

Browse files
jmyrchaJulian Myrcha
andauthored
added socket communication (#14529)
* added socket communication * fixed timeout problem * changed Location parameter to reference * clang --------- Co-authored-by: Julian Myrcha <jmyrcha@cern.ch>
1 parent c62aef2 commit 0e23762

18 files changed

+536
-121
lines changed

EventVisualisation/DataConverter/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ o2_add_library(EventVisualisationDataConverter
1818
src/VisualisationEventJSONSerializer.cxx
1919
src/VisualisationEventROOTSerializer.cxx
2020
src/VisualisationEventOpenGLSerializer.cxx
21+
src/Location.cxx
2122
PUBLIC_LINK_LIBRARIES RapidJSON::RapidJSON
2223
O2::ReconstructionDataFormats
2324
O2::DataFormatsParameters
@@ -33,6 +34,7 @@ o2_add_executable(eve-convert
3334
src/VisualisationTrack.cxx
3435
src/VisualisationCluster.cxx
3536
src/VisualisationCalo.cxx
37+
src/Location.cxx
3638
PUBLIC_LINK_LIBRARIES
3739
O2::EventVisualisationView
3840
RapidJSON::RapidJSON
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
///
13+
/// \file Location.h
14+
/// \author Julian Myrcha
15+
///
16+
17+
#ifndef O2EVE_LOCATION_H
18+
#define O2EVE_LOCATION_H
19+
20+
#include <string>
21+
#include <fstream>
22+
#include <iosfwd>
23+
24+
namespace o2::event_visualisation
25+
{
26+
struct LocationParams {
27+
std::string fileName;
28+
int port = -1;
29+
int timeout = 100;
30+
std::string host = "localhost";
31+
bool toFile = true;
32+
bool toSocket = true;
33+
};
34+
class Location
35+
{
36+
std::ofstream* mOut;
37+
int mClientSocket;
38+
bool mToFile;
39+
bool mToSocket;
40+
std::string mFileName;
41+
int mPort;
42+
int mTimeout;
43+
std::string mHostName;
44+
45+
public:
46+
explicit Location(const LocationParams& params)
47+
{
48+
this->mFileName = params.fileName;
49+
this->mToFile = !params.fileName.empty() && params.toFile;
50+
this->mToSocket = params.port != -1 && params.toSocket;
51+
this->mOut = nullptr;
52+
this->mPort = params.port;
53+
this->mHostName = params.host;
54+
this->mClientSocket = -1;
55+
this->mTimeout = params.timeout;
56+
}
57+
~Location()
58+
{
59+
close();
60+
}
61+
void open();
62+
void close();
63+
void write(char* buf, std::streamsize size);
64+
[[nodiscard]] std::string fileName() const { return this->mFileName; }
65+
[[nodiscard]] std::string hostName() const { return this->mHostName; }
66+
[[nodiscard]] int port() const { return this->mPort; }
67+
};
68+
} // namespace o2::event_visualisation
69+
70+
#endif // O2EVE_LOCATION_H

EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventJSONSerializer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class VisualisationEventJSONSerializer : public VisualisationEventSerializer
5656

5757
public:
5858
bool fromFile(VisualisationEvent& event, std::string fileName) override;
59-
void toFile(const VisualisationEvent& event, std::string fileName) override;
59+
void toFile(const VisualisationEvent& event, Location& location) override;
6060
~VisualisationEventJSONSerializer() override = default;
6161
};
6262

EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventOpenGLSerializer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class VisualisationEventOpenGLSerializer : public VisualisationEventSerializer
3838
public:
3939
const std::string serializerName() const override { return std::string("VisualisationEventOpenGLSerializer"); }
4040
bool fromFile(VisualisationEvent& event, std::string fileName) override;
41-
void toFile(const VisualisationEvent& event, std::string fileName) override;
41+
void toFile(const VisualisationEvent& event, Location& location) override;
4242
~VisualisationEventOpenGLSerializer() override = default;
4343
};
4444

EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventROOTSerializer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class VisualisationEventROOTSerializer : public VisualisationEventSerializer
4444
public:
4545
[[nodiscard]] const std::string serializerName() const override { return std::string("VisualisationEventROOTSerializer"); }
4646
bool fromFile(VisualisationEvent& event, std::string fileName) override;
47-
void toFile(const VisualisationEvent& event, std::string fileName) override;
47+
void toFile(const VisualisationEvent& event, Location& location) override;
4848
~VisualisationEventROOTSerializer() override = default;
4949
};
5050

EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventSerializer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define O2EVE_VISUALISATIONEVENTSERIALIZER_H
1818

1919
#include "EventVisualisationDataConverter/VisualisationEvent.h"
20+
#include "EventVisualisationDataConverter/Location.h"
2021
#include <string>
2122
#include <map>
2223

@@ -45,7 +46,7 @@ class VisualisationEventSerializer
4546
static o2::dataformats::GlobalTrackID deserialize(unsigned source, unsigned index, unsigned flags);
4647
static VisualisationEventSerializer* getInstance(std::string ext) { return instances[ext]; }
4748
virtual bool fromFile(VisualisationEvent& event, std::string fileName) = 0;
48-
virtual void toFile(const VisualisationEvent& event, std::string fileName) = 0;
49+
virtual void toFile(const VisualisationEvent& event, Location& location) = 0;
4950
virtual const std::string serializerName() const = 0;
5051
virtual ~VisualisationEventSerializer() = default;
5152
};
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
///
13+
/// \file Location.cxx
14+
/// \author Julian Myrcha
15+
///
16+
17+
#include "EventVisualisationDataConverter/Location.h"
18+
#include <fairlogger/Logger.h>
19+
#include <sys/socket.h>
20+
#include <unistd.h>
21+
#include <netdb.h>
22+
#include <fcntl.h>
23+
#include <poll.h>
24+
#include <ctime>
25+
26+
using namespace std;
27+
28+
namespace o2::event_visualisation
29+
{
30+
31+
int connect_with_timeout(const int socket, const struct sockaddr* addr, socklen_t addrlen, const unsigned int timeout_ms)
32+
{
33+
int connection = 0;
34+
// Setting O_NONBLOCK
35+
int socket_flags_before;
36+
if ((socket_flags_before = fcntl(socket, F_GETFL, 0) < 0)) {
37+
return -1;
38+
}
39+
if (fcntl(socket, F_SETFL, socket_flags_before | O_NONBLOCK) < 0) {
40+
return -1;
41+
}
42+
do {
43+
if (connect(socket, addr, addrlen) < 0) {
44+
if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
45+
connection = -1; // error
46+
} else { // wait for complete
47+
// deadline 'timeout' ms from now
48+
timespec now; // NOLINT(*-pro-type-member-init)
49+
if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) {
50+
connection = -1;
51+
break;
52+
}
53+
const timespec deadline = {.tv_sec = now.tv_sec,
54+
.tv_nsec = now.tv_nsec + timeout_ms * 1000000l};
55+
do {
56+
if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) {
57+
connection = -1;
58+
break;
59+
}
60+
// compute remaining deadline
61+
const int ms_until_deadline = static_cast<int>((deadline.tv_sec - now.tv_sec) * 1000l + (deadline.tv_nsec - now.tv_nsec) / 1000000l);
62+
if (ms_until_deadline < 0) {
63+
connection = 0;
64+
break;
65+
}
66+
pollfd connectionPool[] = {{.fd = socket, .events = POLLOUT}};
67+
connection = poll(connectionPool, 1, ms_until_deadline);
68+
69+
if (connection > 0) { // confirm the success
70+
int error = 0;
71+
socklen_t len = sizeof(error);
72+
if (getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, &len) == 0) {
73+
errno = error;
74+
}
75+
if (error != 0) {
76+
connection = -1;
77+
}
78+
}
79+
} while (connection == -1 && errno == EINTR); // If interrupted, try again.
80+
if (connection == 0) {
81+
errno = ETIMEDOUT;
82+
connection = -1;
83+
}
84+
}
85+
}
86+
} while (false);
87+
// Restore socket state
88+
if (fcntl(socket, F_SETFL, socket_flags_before) < 0) {
89+
return -1;
90+
}
91+
return connection;
92+
}
93+
94+
void Location::open()
95+
{
96+
if (this->mToFile) {
97+
this->mOut = new std::ofstream(mFileName, std::ios::out | std::ios::binary);
98+
}
99+
if (this->mToSocket) {
100+
// resolve host name
101+
sockaddr_in serverAddress; // NOLINT(*-pro-type-member-init)
102+
serverAddress.sin_family = AF_INET;
103+
serverAddress.sin_port = htons(this->mPort); // Port number
104+
105+
// ask once
106+
static auto server = gethostbyname(this->mHostName.c_str());
107+
if (server == nullptr) {
108+
LOGF(info, "Error no such host %s", this->mHostName.c_str());
109+
return;
110+
};
111+
112+
bcopy((char*)server->h_addr,
113+
(char*)&serverAddress.sin_addr.s_addr,
114+
server->h_length);
115+
116+
// Connect to the server
117+
this->mClientSocket = socket(AF_INET, SOCK_STREAM, 0);
118+
if (this->mClientSocket == -1) {
119+
LOGF(info, "Error creating socket");
120+
return;
121+
}
122+
123+
if (connect_with_timeout(this->mClientSocket, (sockaddr*)&serverAddress,
124+
sizeof(serverAddress), this->mTimeout) == -1) {
125+
LOGF(info, "Error connecting to %s:%d", this->mHostName.c_str(), this->mPort);
126+
::close(this->mClientSocket);
127+
this->mClientSocket = -1;
128+
return;
129+
}
130+
try {
131+
char buf[256] = "SEND:";
132+
strncpy(buf + 6, this->mFileName.c_str(), sizeof(buf) - 7);
133+
strncpy(buf + sizeof(buf) - 6, "ALICE", 6);
134+
auto real = send(this->mClientSocket, buf, sizeof(buf), 0);
135+
if (real != sizeof(buf)) {
136+
throw real;
137+
}
138+
} catch (...) {
139+
::close(this->mClientSocket);
140+
this->mClientSocket = -1;
141+
LOGF(info, "Error sending file name to %s:%d", this->mHostName.c_str(), this->mPort);
142+
}
143+
}
144+
}
145+
146+
void Location::close()
147+
{
148+
if (this->mToFile && this->mOut) {
149+
this->mOut->close();
150+
delete this->mOut;
151+
this->mOut = nullptr;
152+
}
153+
if (this->mToSocket && this->mClientSocket != -1) {
154+
::close(this->mClientSocket);
155+
this->mClientSocket = -1;
156+
}
157+
}
158+
159+
void Location::write(char* buf, std::streamsize size)
160+
{
161+
if (size == 0) {
162+
return;
163+
}
164+
if (this->mToFile && this->mOut) {
165+
this->mOut->write(buf, size);
166+
}
167+
if (this->mToSocket && this->mClientSocket != -1) {
168+
LOGF(info, "Location::write() socket %s ++++++++++++++++++++++", fileName());
169+
try {
170+
auto real = send(this->mClientSocket, buf, size, 0);
171+
if (real != size) {
172+
throw real;
173+
}
174+
} catch (...) {
175+
::close(this->mClientSocket);
176+
this->mClientSocket = -1;
177+
LOGF(info, "Error sending data to %s:%d", this->mHostName.c_str(), this->mPort);
178+
}
179+
}
180+
}
181+
182+
} // namespace o2::event_visualisation

EventVisualisation/DataConverter/src/VisualisationEventJSONSerializer.cxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ using namespace rapidjson;
2929
namespace o2::event_visualisation
3030
{
3131

32-
void VisualisationEventJSONSerializer::toFile(const VisualisationEvent& event, std::string fileName)
32+
void VisualisationEventJSONSerializer::toFile(const VisualisationEvent& event, Location& location)
3333
{
34+
std::string fileName = location.fileName();
3435
std::string json = toJson(event);
3536
std::ofstream out(fileName);
3637
out << json;

0 commit comments

Comments
 (0)