MCS: Simplify and cleanup the HostListener
[remote/remote-mci.git] / mcs / Host.cc
blobefacb4d8fc99a7b430db551177de131544f67d05
1 #include "Host.h"
2 #include "macros.h"
4 namespace remote { namespace 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(std::string 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(std::string 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::findOrCreateMote(MsgMoteConnectionInfo& info)
66 std::string path = info.getPath().getString();
67 std::string mac = info.getMac();
68 mysqlpp::Connection& sqlConn = dbConn.getConnection();
69 dbkey_t site_id, mote_id;
70 Mote* mote;
71 mysqlpp::ResUse selectRes;
72 mysqlpp::ResNSel execRes;
73 mysqlpp::Row row;
75 log("Mote %s plugged at %s\n", mac.c_str(), path.c_str());
77 mysqlpp::Query query = sqlConn.query();
79 query << "select site_id from path"
80 " where host_id = " << id
81 << " and path = " << mysqlpp::quote << path;
83 // look for the connection path + host id to get the site_id
84 selectRes = query.use();
85 selectRes.disable_exceptions();
86 row = selectRes.fetch_row();
87 if (!row || row.empty()) {
88 // if not found, create the path in the database with no site_id
89 query.reset();
90 query << "insert into path(host_id,path) "
91 << "values(" << id << "," << mysqlpp::quote << path << ")";
93 query.execute(); // TODO: error checking
95 // XXX: Set to the default site_id for new paths
96 site_id = 1;
98 } else {
99 site_id = (dbkey_t) row["site_id"];
102 // look for the mac addresses in the database, get mote_id
103 query.reset();
104 query << "select mote_id from moteattr ma, mote_moteattr mma, moteattrtype mat"
105 " where ma.val=" << mysqlpp::quote << mac
106 << " and mma.moteattr_id=ma.id"
107 " and ma.moteattrtype_id=mat.id"
108 " and mat.name='macaddress'";
110 selectRes.purge();
111 selectRes = query.use();
112 selectRes.disable_exceptions();
113 row = selectRes.fetch_row();
115 MoteAddresses *newtarget = new MoteAddresses(mac);
117 if ( !row || row.empty() )
119 std::ostringstream oss;
121 selectRes.purge();
122 // create the mote using site_id only - the mote class will create the
123 // mote database record itself
124 mote = new Mote(site_id,(MoteControlInfrastructure&)*this,*newtarget);
125 // TODO: error checking
126 // create the mac and net address database records using the mote id
127 oss << (uint16_t) mote->mote_id;
128 newtarget->netAddress = oss.str();
130 log("Attributes: macaddress=%s netaddress=%s platform=%s\n",
131 mac.c_str(), newtarget->netAddress.c_str(),
132 info.getPlatform().c_str());
133 mote->setAttribute("macaddress", mac);
134 mote->setAttribute("netaddress", newtarget->netAddress);
135 mote->setAttribute("platform", info.getPlatform());
137 else
139 mote_id = (dbkey_t) row["mote_id"]; // save the mote_id
140 selectRes.purge();
141 // create the mote object using mote_id and site_id - the mote class will
142 // update the mote database record to reflect the new site
143 mote = new Mote(mote_id,site_id,(MoteControlInfrastructure&)*this,*newtarget);
145 // get the net address mote attribute
146 newtarget->netAddress = mote->getAttribute("netaddress");
147 // TODO: error checking
150 if (mote)
152 // finally, register the new mote in the local map
153 registerMoteByMac(mac, mote);
157 void Host::handleMotesLostList(MsgMoteConnectionInfoList& infolist)
159 MsgMoteConnectionInfo info;
161 while (infolist.getNextMoteInfo(info))
162 deleteMoteByMac(info.getMac());
165 void Host::handleMotesFoundList(MsgMoteConnectionInfoList& infolist)
167 MsgMoteConnectionInfo info;
169 while (infolist.getNextMoteInfo(info)) {
170 findOrCreateMote(info);
174 void Host::request(MCIAddress& address, MsgPayload& request )
176 MsgMoteAddresses addresses(((MoteAddresses&)address).mac,
177 ((MoteAddresses&)address).netAddress);
178 MsgHostRequest msgHostRequest(addresses,request);
179 HostMsg message(msgHostRequest);
181 try {
182 Message msg;
183 msg.sendMsg(fd,message);
185 catch (remote::protocols::MMSException e)
187 log("Exception: %s\n",e.what());
188 this->destroy(true);
193 void Host::handleEvent(short events)
196 if ( (events & POLLIN) || (events & POLLPRI) )
198 if (!message_in.nonBlockingRecv(fd))
200 return;
203 uint32_t msglen = message_in.getLength();
204 uint8_t* buffer = message_in.getData();
205 HostMsg message(buffer,msglen);
207 switch (message.getType())
209 case HOSTMSGTYPE_HOSTCONFIRM:
210 handleMsgIn(message.getHostConfirm());
211 break;
212 case HOSTMSGTYPE_PLUGEVENT:
213 if ( message.getPlugEvent().getType() == PLUG_MOTES )
215 handleMotesFoundList(message.getPlugEvent().getInfoList());
217 else if ( message.getPlugEvent().getType() == UNPLUG_MOTES )
219 handleMotesLostList(message.getPlugEvent().getInfoList());
221 else
223 __THROW__ ("Invalid plugevent received from host!");
225 break;
226 default:
227 __THROW__ ("Invalid message type received from host!");
228 break;
231 else if ( (events & POLLERR) || (events & POLLHUP) || (events & POLLNVAL) )
233 __THROW__ ("Host connection error!\n");
237 void Host::handleMsgIn(MsgHostConfirm& msgHostConfirm)
239 motemapbymac_t::iterator mI;
241 mI = motesByMac.find(msgHostConfirm.getMoteAddresses().getMac());
242 if (mI != motesByMac.end()) {
243 if (msgHostConfirm.getStatus() == MSGHOSTCONFIRM_UNKNOWN_MOTE) {
244 deleteMoteByMac(msgHostConfirm.getMoteAddresses().getMac());
245 } else {
246 mI->second->confirm(msgHostConfirm.getMessage());