YARP
Yet Another Robot Platform
AllocatorOnTriples.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <cstdio>
8 #include <cstdlib>
9 
12 
13 using namespace yarp::os;
14 using namespace yarp::serversql::impl;
15 
16 namespace {
17 YARP_SERVERSQL_LOG_COMPONENT(ALLOCATORONTRIPLES, "yarp.serversql.impl.AllocatorOnTriples")
18 } // namespace
19 
20 Contact AllocatorOnTriples::completePortName(const Contact& c) {
21  std::string name;
22  Triple t;
23  t.setNsNameValue("alloc","tmpid","*");
24  TripleContext context;
25  context.setRid(db->find(t, nullptr));
26  if (context.rid>=0) {
27  t.setNsNameValue("alloc","*","free");
28  std::list<Triple> match = db->query(t,&context);
29  if (match.size()>0) {
30  name = match.begin()->name;
31  }
32  }
33 
34  if (name=="") {
35  if (tmpid==-1) {
36  t.setNsNameValue("alloc","tmpid","*");
37  std::list<Triple> lst = db->query(t, nullptr);
38  if (lst.size()>0) {
39  tmpid = atoi(lst.begin()->value.c_str());
40  }
41  if (tmpid==-1) {
42  tmpid = 0;
43  }
44  }
45  tmpid++;
46  char buf[256];
47  std::snprintf(buf, 256, "%d", tmpid);
48  t.setNsNameValue("alloc","tmpid",buf);
49  db->update(t, nullptr);
50  t.setNsNameValue("alloc","tmpid","*");
51  context.setRid(db->find(t, nullptr));
52  std::snprintf(buf, 256, "/tmp/port/%u", tmpid);
53  name = buf;
54  }
55 
56  t.setNsNameValue("alloc",name.c_str(),"in_use");
57  db->update(t,&context);
58 
59  return Contact(name,
60  c.getCarrier(),
61  c.getHost(),
62  c.getPort());
63 }
64 
65 
66 Contact AllocatorOnTriples::completeSocket(const Contact& c) {
67  Contact tmp = completeHost(c);
68  return completePortNumber(tmp);
69 }
70 
71 Contact AllocatorOnTriples::completePortNumber(const Contact& c) {
72  if (c.getPort()!=-1 && c.getPort()!=0) {
73  return c;
74  }
75 
76  // unlike standard yarp name server, port number allocation
77  // is global across the network, rather than per machine.
78 
79  // we also try to keep port numbers stable for port names,
80  // when possible.
81 
82  std::string npref;
83  int pref = -1;
84  std::string nstring;
85  int number = -1;
86  Triple t;
87  t.setNsNameValue("alloc","regid","*");
88  TripleContext context;
89  context.setRid(db->find(t, nullptr));
90  if (context.rid>=0) {
91  t.setNsNameValue("prefer","*",c.getName().c_str());
92  std::list<Triple> match = db->query(t,&context);
93  if (match.size()>0) {
94  npref = match.begin()->name;
95  pref = atoi(npref.c_str());
96  t.setNsNameValue("alloc",npref.c_str(),"in_use");
97  match = db->query(t,&context);
98  if (match.size()==0) {
99  nstring = npref;
100  number = pref;
101  }
102  }
103  }
104 
105  if (nstring=="") {
106  if (regid==-1) {
107  Triple t;
108  t.setNsNameValue("alloc","regid","*");
109  std::list<Triple> lst = db->query(t, nullptr);
110  if (lst.size()>0) {
111  regid = atoi(lst.begin()->value.c_str());
112  }
113  if (regid==-1) {
114  regid = config.minPortNumber-1;
115  }
116  }
117  if (regid>=config.maxPortNumber && config.maxPortNumber!=0) {
118  if (nstring == "") {
119  t.setNsNameValue("alloc","*","free");
120  std::list<Triple> match = db->query(t,&context);
121  if (match.size()>0) {
122  nstring = match.begin()->name;
123  number = atoi(nstring.c_str());
124  }
125  }
126  if (nstring=="") {
127  yCError(ALLOCATORONTRIPLES, "Ran out of port numbers");
128  yCError(ALLOCATORONTRIPLES, "* Make sure ports/programs get closed properly.");
129  yCError(ALLOCATORONTRIPLES, "* If programs terminate without closing ports, run \"yarp clean\" from time to time..");
130  std::exit(1);
131  }
132  } else {
133  regid++;
134  Triple t;
135  char buf[256];
136  std::snprintf(buf, 256, "%d", regid);
137  t.setNsNameValue("alloc","regid",buf);
138  db->update(t, nullptr);
139  t.setNsNameValue("alloc","regid","*");
140  context.setRid(db->find(t, nullptr));
141  nstring = buf;
142  number = regid;
143  }
144  }
145  t.setNsNameValue("alloc",nstring.c_str(),"in_use");
146  db->update(t,&context);
147  t.setNsNameValue("prefer",nstring.c_str(),c.getName().c_str());
148  db->update(t,&context);
149 
150  Contact contact = c;
151  contact.setPort(number);
152  return contact;
153 }
154 
155 
156 Contact AllocatorOnTriples::completeHost(const yarp::os::Contact& c) {
157  // deal with allocating multicast ips
158 
159  if (c.getCarrier()!="mcast") {
160  return c;
161  }
162  if (c.getHost()!="...") {
163  return c;
164  }
165 
166  std::string name;
167  Triple t;
168  t.setNsNameValue("alloc","mcastCursor","*");
169  TripleContext context;
170  context.setRid(db->find(t, nullptr));
171  if (context.rid>=0) {
172  t.setNsNameValue("alloc","*","free");
173  std::list<Triple> match = db->query(t,&context);
174  if (match.size()>0) {
175  name = match.begin()->name;
176  }
177  }
178 
179  if (name=="") {
180  if (mcastCursor==-1) {
181  t.setNsNameValue("alloc","mcastCursor","*");
182  std::list<Triple> lst = db->query(t, nullptr);
183  if (lst.size()>0) {
184  mcastCursor = atoi(lst.begin()->value.c_str());
185  }
186  if (mcastCursor==-1) {
187  mcastCursor = 1;
188  }
189  }
190  mcastCursor++;
191  char buf[256];
192  std::snprintf(buf, 256, "%d", mcastCursor);
193  t.setNsNameValue("alloc","mcastCursor",buf);
194  db->update(t, nullptr);
195  t.setNsNameValue("alloc","mcastCursor","*");
196  context.setRid(db->find(t, nullptr));
197 
198  int v1 = mcastCursor%255;
199  int v2 = mcastCursor/255;
200  if (v2>=255) {
201  yCError(ALLOCATORONTRIPLES, "Ran out of mcast addresses");
202  std::exit(1);
203  }
204  std::snprintf(buf, 256, "224.1.%d.%d", v2+1, v1+1);
205  name = buf;
206  }
207 
208  t.setNsNameValue("alloc",name.c_str(),"in_use");
209  db->update(t,&context);
210 
211  Contact contact = c;
212  contact.setHost(name);
213  return contact;
214 }
215 
216 
217 bool AllocatorOnTriples::freePortResources(const yarp::os::Contact& c) {
218  std::string portName = c.getName();
219  int portNumber = c.getPort();
220  std::string hostName = c.getHost();
221 
222  // free up automatic name for port, if one was allocated
223  Triple t;
224  t.setNsNameValue("alloc","tmpid","*");
225  TripleContext context;
226  context.setRid(db->find(t, nullptr));
227  t.setNsNameValue("alloc",portName.c_str(),"in_use");
228  if (db->find(t,&context)>=0) {
229  t.setNsNameValue("alloc",portName.c_str(),"free");
230  db->update(t,&context);
231  }
232 
233  t.setNsNameValue("alloc","regid","*");
234  context.setRid(db->find(t, nullptr));
235  char buf[256];
236  std::snprintf(buf, 256, "%d", portNumber);
237  t.setNsNameValue("alloc",buf,"in_use");
238  if (db->find(t,&context)>=0) {
239  t.setNsNameValue("alloc",buf,"free");
240  db->update(t,&context);
241  }
242 
243  t.setNsNameValue("alloc","mcastCursor","*");
244  context.setRid(db->find(t, nullptr));
245  t.setNsNameValue("alloc",hostName.c_str(),"in_use");
246  if (db->find(t,&context)>=0) {
247  t.setNsNameValue("alloc",hostName.c_str(),"free");
248  db->update(t,&context);
249  }
250 
251  return true;
252 }
float t
Represents how to reach a part of a YARP network.
Definition: Contact.h:36
void setHost(const std::string &hostname)
Set the host name to be the input parameter.
Definition: Contact.cpp:233
std::string getName() const
Get the name associated with this Contact.
Definition: Contact.cpp:205
void setPort(int port)
Set the port number to be the input parameter.
Definition: Contact.cpp:244
int getPort() const
Get the port number associated with this Contact for socket communication.
Definition: Contact.cpp:239
std::string getCarrier() const
Get the carrier associated with this Contact for socket communication.
Definition: Contact.cpp:250
std::string getHost() const
Get the host name associated with this Contact for socket communication.
Definition: Contact.cpp:228
Side information for controlling access to triples.
Definition: TripleSource.h:24
The basic unit of data the name server works with.
Definition: Triple.h:25
#define yCError(component,...)
Definition: LogComponent.h:154
#define YARP_SERVERSQL_LOG_COMPONENT(name, name_string)
Definition: LogComponent.h:34
An interface to the operating system, including Port based communication.