Initial commit
[remote/remote-mci.git] / diku_mcs / Host.cc
blob587d8f98ffa5629ed86320541d3d9fa9fcda838d
1 #include "Host.h"
2 #include "macros.h"
4 namespace remote { namespace diku_mcs {
6 Host::Host( int fd, dbkey_t p_id, std::string ip, hostmapbykey_t& p_hostMap )
7 : FileDescriptor(fd), id(p_id), message_in(), ipaddress(ip), hostMap(p_hostMap)
9 hostMap[id] = this;
10 protocols::setSendTimeout( fd,5,0); // 5 second host send timeout should be adequate
11 // set keepalive options: 3 attempts after 120 seconds, 30 second interval
12 setKeepAlive( fd, 3, 120, 30);
15 Host::~Host()
17 log("Closing host %s!\n",ipaddress.c_str());
18 hostMap.erase(id);
21 void Host::destroy(bool silent)
23 log("Deleting motes\n");
24 motemapbymac_t::iterator mI;
25 for( mI = motesByMac.begin(); mI != motesByMac.end(); mI++)
27 if (mI->second) mI->second->destroy(silent);
29 delete this;
32 void Host::registerMoteByMac(uint64_t mac,Mote* mote)
34 motemapbymac_t::iterator mI;
36 mI = motesByMac.find(mac);
38 if ( mI != motesByMac.end() )
40 mI->second->destroy();
43 motesByMac[mac] = mote;
46 void Host::deleteMoteByMac(uint64_t mac)
48 motemapbymac_t::iterator mI;
49 Mote* mote = NULL;
50 mI = motesByMac.find(mac);
52 if ( mI != motesByMac.end() )
54 mote = mI->second;
55 motesByMac.erase(mI);
58 if (mote)
60 mote->destroy();
64 void Host::registerMoteInfoByMac(uint64_t mac, moteinfo_t moteinfo)
66 moteInfoByMac[mac] = moteinfo;
69 void Host::deleteMoteInfoByMac(uint64_t mac)
71 moteinfobymac_t::iterator mI;
72 mI = moteInfoByMac.find(mac);
73 if ( mI != moteInfoByMac.end() )
75 moteInfoByMac.erase(mI);
79 void Host::findOrCreateMote(MsgMoteConnectionInfo& info)
81 mysqlpp::Connection& sqlConn = dbConn.getConnection();
82 dbkey_t site_id, mote_id;
83 Mote* mote;
84 mysqlpp::ResUse selectRes;
85 mysqlpp::ResNSel execRes;
86 mysqlpp::Row row;
88 mysqlpp::Query siteselect = sqlConn.query();
89 mysqlpp::Query moteselect = sqlConn.query();
90 mysqlpp::Query tosselect = sqlConn.query();
92 mysqlpp::Query pathinsert = sqlConn.query();
93 mysqlpp::Query macinsert = sqlConn.query();
94 mysqlpp::Query tosinsert = sqlConn.query();
96 siteselect << "select site_id from path \
97 where host_id = %0:hostid \
98 and path='%1:path'";
100 moteselect << "select mote_id from macaddress \
101 where macaddress = %0:macaddress";
103 tosselect << "select tosaddress from tosaddress \
104 where mote_id = %0:mote_id";
106 pathinsert << "insert into path(host_id,path) \
107 values( %0:hostid,'%1:path' )";
109 macinsert << "insert into macaddress(macaddress,mote_id) \
110 values ( %0:macaddress,%1:mote_id)";
112 tosinsert << "insert into tosaddress(mote_id) values( %0:mote_id )";
114 moteselect.parse();
115 siteselect.parse();
116 tosselect.parse();
118 pathinsert.parse();
119 macinsert.parse();
120 tosinsert.parse();
123 // look for the connection path + host id to get the site_id
124 siteselect.def["hostid"] = id;
125 siteselect.def["path"] = info.getPath().getString();
127 selectRes = siteselect.use();
128 selectRes.disable_exceptions();
129 row = selectRes.fetch_row();
130 if ( !row || row.empty() )
132 // if not found, create the path in the database with no site_id
133 pathinsert.def["hostid"] = id;
134 pathinsert.def["path"] = info.getPath().getString();
135 pathinsert.execute(); // TODO: error checking
137 // get the newly inserted paths site_id
138 selectRes.purge();
139 selectRes = siteselect.use();
140 selectRes.disable_exceptions();
141 row = selectRes.fetch_row();
144 // save the site_id
145 site_id = (dbkey_t) row["site_id"];
147 // look for the mac addresses in the database, get mote_id
148 moteselect.def["macaddress"] = info.macAddress;
150 selectRes.purge();
151 selectRes = moteselect.use();
152 selectRes.disable_exceptions();
153 row = selectRes.fetch_row();
155 MoteAddresses* newtarget = new MoteAddresses(0,info.macAddress);
157 if ( !row || row.empty() )
159 selectRes.purge();
160 // create the mote using site_id only - the mote class will create the
161 // mote database record itself
162 mote = new Mote(site_id,(MoteControlInfrastructure&)*this,*newtarget);
163 // TODO: error checking
164 // create the mac and tos address database records using the mote id
165 macinsert.def["macaddress"] = info.macAddress;
166 macinsert.def["mote_id"] = mote->mote_id;
167 macinsert.execute();
168 tosinsert.def["mote_id"] = mote->mote_id;
169 execRes = tosinsert.execute();
170 newtarget->tosAddress = execRes.insert_id;
171 // FIXME: convert MAC address to hex string!!
172 //mote->setAttribute("macaddress",std::string::info.macAddress);
173 // TODO: tos address as well
175 else
177 mote_id = (dbkey_t) row["mote_id"]; // save the mote_id
178 selectRes.purge();
179 // create the mote object using mote_id and site_id - the mote class will
180 // update the mote database record to reflect the new site
181 mote = new Mote(mote_id,site_id,(MoteControlInfrastructure&)*this,*newtarget);
183 // add tosAddress as external mote info
184 tosselect.def["mote_id"] = mote_id; // get the tos address
185 selectRes = tosselect.use();
186 selectRes.disable_exceptions();
187 row = selectRes.fetch_row();
188 newtarget->tosAddress = (uint16_t)row["tosaddress"];
191 if (mote)
193 // finally, register the new mote in the local map
194 registerMoteByMac(info.macAddress,mote);
198 void Host::handleMotesLostList(MsgMoteConnectionInfoList& infolist)
200 MsgMoteConnectionInfo info;
201 while ( infolist.getNextMoteInfo(info) )
203 deleteMoteByMac(info.macAddress);
204 deleteMoteInfoByMac(info.macAddress);
208 void Host::handleMotesFoundList(MsgMoteConnectionInfoList& infolist)
210 MsgMoteConnectionInfo info;
212 while ( infolist.getNextMoteInfo(info) )
214 uint8_t* m = (uint8_t*)&info.macAddress;
215 log("Mote %02x%02x%02x%02x %02x%02x%02x%02x plugged at %s\n",m[7],m[6],m[5],m[4],m[3],m[2],m[1],m[0],info.getPath().getString().c_str());
217 findOrCreateMote(info);
221 void Host::request(MCIAddress& address, MsgPayload& request )
223 MsgMoteAddresses addresses(((MoteAddresses&)address).tosAddress,
224 ((MoteAddresses&)address).macAddress);
225 MsgHostRequest msgHostRequest(addresses,request);
226 HostMsg message(msgHostRequest);
228 try {
229 Message msg;
230 msg.sendMsg(fd,message);
232 catch (remote::protocols::MMSException e)
234 log("Exception: %s\n",e.what());
235 this->destroy(true);
240 void Host::handleEvent(short events)
243 if ( (events & POLLIN) || (events & POLLPRI) )
245 if (!message_in.nonBlockingRecv(fd))
247 return;
250 uint32_t msglen = message_in.getLength();
251 uint8_t* buffer = message_in.getData();
252 HostMsg message(buffer,msglen);
254 switch (message.getType())
256 case HOSTMSGTYPE_HOSTCONFIRM:
257 handleMsgIn(message.getHostConfirm());
258 break;
259 case HOSTMSGTYPE_PLUGEVENT:
260 if ( message.getPlugEvent().getType() == PLUG_MOTES )
262 handleMotesFoundList(message.getPlugEvent().getInfoList());
264 else if ( message.getPlugEvent().getType() == UNPLUG_MOTES )
266 handleMotesLostList(message.getPlugEvent().getInfoList());
268 else
270 __THROW__ ("Invalid plugevent received from host!");
272 break;
273 default:
274 __THROW__ ("Invalid message type received from host!");
275 break;
278 else if ( (events & POLLERR) || (events & POLLHUP) || (events & POLLNVAL) )
280 __THROW__ ("Host connection error!\n");
284 void Host::handleMsgIn(MsgHostConfirm& msgHostConfirm)
286 motemapbymac_t::iterator mI;
287 mI = motesByMac.find(msgHostConfirm.getMoteAddresses().getMacAddress());
288 if ( mI != motesByMac.end() )
290 if (msgHostConfirm.getStatus() == MSGHOSTCONFIRM_UNKNOWN_MOTE)
292 deleteMoteByMac(msgHostConfirm.getMoteAddresses().getMacAddress());
293 deleteMoteInfoByMac(msgHostConfirm.getMoteAddresses().getMacAddress());
294 } else {
295 mI->second->confirm(msgHostConfirm.getMessage());