Line data Source code
1 :
2 : /* Copyright (c) 2005-2016, Stefan Eilemann <eile@equalizergraphics.com>
3 : *
4 : * This file is part of Collage <https://github.com/Eyescale/Collage>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "connectionDescription.h"
21 :
22 : #include <sstream>
23 :
24 : namespace co
25 : {
26 : #define SEPARATOR '#'
27 :
28 : namespace
29 : {
30 65 : static ConnectionType _getConnectionType(const std::string& string)
31 : {
32 65 : if (string == "TCPIP")
33 65 : return CONNECTIONTYPE_TCPIP;
34 0 : if (string == "TCP")
35 0 : return CONNECTIONTYPE_TCPIP;
36 0 : if (string == "ANON_PIPE")
37 0 : return CONNECTIONTYPE_PIPE;
38 0 : if (string == "PIPE")
39 0 : return CONNECTIONTYPE_NAMEDPIPE;
40 0 : if (string == "RSP")
41 0 : return CONNECTIONTYPE_RSP;
42 0 : if (string == "RDMA")
43 0 : return CONNECTIONTYPE_RDMA;
44 0 : if (string == "UDT")
45 0 : return CONNECTIONTYPE_UDT;
46 :
47 0 : LBWARN << "Unknown connection type: " << string << std::endl;
48 0 : return CONNECTIONTYPE_NONE;
49 : }
50 : }
51 :
52 0 : ConnectionDescription::ConnectionDescription(std::string& data)
53 : : type(CONNECTIONTYPE_TCPIP)
54 : , bandwidth(0)
55 : , port(0)
56 0 : , filename("default")
57 : {
58 0 : fromString(data);
59 0 : LBASSERTINFO(data.empty(), data);
60 0 : }
61 :
62 747 : std::string ConnectionDescription::toString() const
63 : {
64 1494 : std::ostringstream description;
65 746 : serialize(description);
66 1494 : return description.str();
67 : }
68 :
69 812 : void ConnectionDescription::serialize(std::ostream& os) const
70 : {
71 812 : os << type << SEPARATOR << bandwidth << SEPARATOR << hostname << SEPARATOR
72 1624 : << interfacename << SEPARATOR << port << SEPARATOR << filename
73 1623 : << SEPARATOR;
74 811 : }
75 :
76 65 : bool ConnectionDescription::fromString(std::string& data)
77 : {
78 : {
79 65 : size_t nextPos = data.find(SEPARATOR);
80 : // assume hostname[:port][:type] or filename:PIPE format
81 65 : if (nextPos == std::string::npos)
82 : {
83 0 : type = CONNECTIONTYPE_TCPIP;
84 0 : nextPos = data.find(':');
85 0 : if (nextPos == std::string::npos) // assume hostname format
86 : {
87 0 : hostname = data;
88 0 : data.clear();
89 0 : return true;
90 : }
91 :
92 0 : hostname = data.substr(0, nextPos);
93 0 : data = data.substr(nextPos + 1);
94 :
95 0 : while (nextPos != std::string::npos)
96 : {
97 0 : nextPos = data.find(':');
98 0 : const std::string token = data.substr(0, nextPos);
99 0 : data = data.substr(nextPos + 1);
100 :
101 0 : if (!token.empty() && isdigit(token[0])) // port
102 0 : port = atoi(token.c_str());
103 : else
104 : {
105 0 : type = _getConnectionType(token);
106 0 : if (type == CONNECTIONTYPE_NAMEDPIPE)
107 : {
108 0 : filename = hostname;
109 0 : hostname.clear();
110 : }
111 0 : else if (type == CONNECTIONTYPE_NONE)
112 0 : goto error;
113 : }
114 : }
115 :
116 0 : data.clear();
117 0 : return true;
118 : }
119 :
120 : // else assume SEPARATOR-delimited list
121 130 : const std::string typeStr = data.substr(0, nextPos);
122 65 : data = data.substr(nextPos + 1);
123 :
124 65 : type = _getConnectionType(typeStr);
125 :
126 65 : nextPos = data.find(SEPARATOR);
127 65 : if (nextPos == std::string::npos)
128 0 : goto error;
129 :
130 130 : const std::string bandwidthStr = data.substr(0, nextPos);
131 65 : data = data.substr(nextPos + 1);
132 65 : bandwidth = atoi(bandwidthStr.c_str());
133 :
134 65 : nextPos = data.find(SEPARATOR);
135 65 : if (nextPos == std::string::npos)
136 0 : goto error;
137 :
138 65 : hostname = data.substr(0, nextPos);
139 65 : data = data.substr(nextPos + 1);
140 :
141 65 : nextPos = data.find(SEPARATOR);
142 65 : if (nextPos == std::string::npos)
143 0 : goto error;
144 :
145 65 : interfacename = data.substr(0, nextPos);
146 65 : data = data.substr(nextPos + 1);
147 :
148 65 : nextPos = data.find(SEPARATOR);
149 65 : if (nextPos == std::string::npos)
150 0 : goto error;
151 :
152 130 : const std::string portStr = data.substr(0, nextPos);
153 65 : data = data.substr(nextPos + 1);
154 65 : port = atoi(portStr.c_str());
155 :
156 65 : nextPos = data.find(SEPARATOR);
157 65 : if (nextPos == std::string::npos)
158 0 : goto error;
159 :
160 65 : filename = data.substr(0, nextPos);
161 65 : data = data.substr(nextPos + 1);
162 : }
163 65 : return true;
164 :
165 : error:
166 0 : LBWARN << "Could not parse connection description: " << data << std::endl;
167 0 : return false;
168 : }
169 :
170 121 : void ConnectionDescription::setHostname(const std::string& hostname_)
171 : {
172 121 : hostname = hostname_;
173 121 : }
174 :
175 0 : void ConnectionDescription::setInterface(const std::string& interface_)
176 : {
177 0 : interfacename = interface_;
178 0 : }
179 :
180 0 : void ConnectionDescription::setFilename(const std::string& filename_)
181 : {
182 0 : filename = filename_;
183 0 : }
184 :
185 0 : const std::string& ConnectionDescription::getFilename() const
186 : {
187 0 : return filename;
188 : }
189 :
190 238 : const std::string& ConnectionDescription::getHostname() const
191 : {
192 238 : return hostname;
193 : }
194 :
195 0 : const std::string& ConnectionDescription::getInterface() const
196 : {
197 0 : return interfacename;
198 : }
199 :
200 0 : bool ConnectionDescription::isSameMulticastGroup(
201 : ConstConnectionDescriptionPtr rhs)
202 : {
203 0 : return (type >= CONNECTIONTYPE_MULTICAST && type == rhs->type &&
204 0 : hostname == rhs->hostname && port == rhs->port);
205 : }
206 :
207 0 : bool ConnectionDescription::operator==(const ConnectionDescription& rhs) const
208 : {
209 0 : return type == rhs.type && bandwidth == rhs.bandwidth && port == rhs.port &&
210 0 : hostname == rhs.hostname && interfacename == rhs.interfacename &&
211 0 : filename == rhs.filename;
212 : }
213 :
214 66 : std::string serialize(const ConnectionDescriptions& descriptions)
215 : {
216 132 : std::ostringstream data;
217 66 : data << descriptions.size() << CO_SEPARATOR;
218 :
219 393 : for (ConnectionDescriptions::const_iterator i = descriptions.begin();
220 262 : i != descriptions.end(); ++i)
221 : {
222 130 : ConnectionDescriptionPtr desc = *i;
223 65 : desc->serialize(data);
224 : }
225 :
226 132 : return data.str();
227 : }
228 :
229 66 : bool deserialize(std::string& data, ConnectionDescriptions& descriptions)
230 : {
231 66 : if (!descriptions.empty())
232 0 : LBWARN << "Connection descriptions already hold data before deserialize"
233 0 : << std::endl;
234 :
235 : // num connection descriptions
236 66 : size_t nextPos = data.find(CO_SEPARATOR);
237 66 : if (nextPos == std::string::npos || nextPos == 0)
238 : {
239 0 : LBERROR << "Could not parse number of connection descriptions"
240 0 : << std::endl;
241 0 : return false;
242 : }
243 :
244 132 : const std::string sizeStr = data.substr(0, nextPos);
245 66 : if (!isdigit(sizeStr[0]))
246 : {
247 0 : LBERROR << "Could not parse number of connection descriptions"
248 0 : << std::endl;
249 0 : return false;
250 : }
251 :
252 66 : const size_t nDesc = atoi(sizeStr.c_str());
253 66 : data = data.substr(nextPos + 1);
254 :
255 : // connection descriptions
256 131 : for (size_t i = 0; i < nDesc; ++i)
257 : {
258 130 : ConnectionDescriptionPtr desc = new ConnectionDescription;
259 65 : if (!desc->fromString(data))
260 : {
261 0 : LBERROR << "Error during connection description parsing"
262 0 : << std::endl;
263 0 : return false;
264 : }
265 65 : descriptions.push_back(desc);
266 : }
267 :
268 66 : return true;
269 : }
270 :
271 0 : std::ostream& operator<<(std::ostream& os, const ConnectionDescription& desc)
272 : {
273 0 : os << lunchbox::disableFlush << lunchbox::disableHeader << "connection"
274 0 : << std::endl
275 0 : << "{" << std::endl
276 0 : << lunchbox::indent << "type " << desc.type << std::endl
277 0 : << "hostname \"" << desc.getHostname() << "\"" << std::endl;
278 :
279 0 : if (!desc.getInterface().empty())
280 0 : os << "interface \"" << desc.getInterface() << "\"" << std::endl;
281 :
282 0 : if (desc.port != 0)
283 0 : os << "port " << desc.port << std::endl;
284 :
285 0 : if (!desc.getFilename().empty())
286 0 : os << "filename \"" << desc.getFilename() << "\"" << std::endl;
287 :
288 0 : if (desc.bandwidth != 0)
289 0 : os << "bandwidth " << desc.bandwidth << std::endl;
290 :
291 0 : return os << lunchbox::exdent << "}" << lunchbox::enableHeader
292 0 : << lunchbox::enableFlush << std::endl;
293 : }
294 63 : }
|