3 namespace remote
{ namespace mcs
{
5 Host::Host( int fd
, dbkey_t p_id
, std::string ip
, hostmapbykey_t
& p_hostMap
)
6 : FileDescriptor(fd
), id(p_id
), message_in(), ipaddress(ip
), hostMap(p_hostMap
)
9 protocols::setSendTimeout( fd
,5,0); // 5 second host send timeout should be adequate
10 // set keepalive options: 3 attempts after 120 seconds, 30 second interval
11 setKeepAlive( fd
, 3, 120, 30);
16 Log::info("Closing host %s!", ipaddress
.c_str());
20 void Host::destroy(bool silent
)
22 motemapbymac_t::iterator mI
;
24 Log::info("Deleting motes");
25 for(mI
= motesByMac
.begin(); mI
!= motesByMac
.end(); mI
++)
27 mI
->second
->destroy(silent
);
31 void Host::registerMoteByMac(std::string mac
, Mote
*mote
)
33 motemapbymac_t::iterator mI
;
35 mI
= motesByMac
.find(mac
);
37 if ( mI
!= motesByMac
.end() )
39 mI
->second
->destroy();
42 motesByMac
[mac
] = mote
;
45 void Host::deleteMoteByMac(std::string mac
)
47 motemapbymac_t::iterator mI
;
49 mI
= motesByMac
.find(mac
);
51 if ( mI
!= motesByMac
.end() )
63 void Host::findOrCreateMote(MsgMoteConnectionInfo
& info
)
65 std::string path
= info
.getPath().getString();
66 std::string mac
= info
.getMac();
67 mysqlpp::Connection
& sqlConn
= dbConn
.getConnection();
68 dbkey_t site_id
, mote_id
;
70 mysqlpp::ResUse selectRes
;
71 mysqlpp::ResNSel execRes
;
74 Log::info("Mote %s plugged at %s", mac
.c_str(), path
.c_str());
76 mysqlpp::Query query
= sqlConn
.query();
78 query
<< "select site_id from path"
79 " where host_id = " << id
80 << " and path = " << mysqlpp::quote
<< path
;
82 // look for the connection path + host id to get the site_id
83 selectRes
= query
.use();
84 selectRes
.disable_exceptions();
85 row
= selectRes
.fetch_row();
86 if (!row
|| row
.empty()) {
87 // if not found, create the path in the database with no site_id
89 query
<< "insert into path(host_id,path) "
90 << "values(" << id
<< "," << mysqlpp::quote
<< path
<< ")";
92 query
.execute(); // TODO: error checking
94 // XXX: Set to the default site_id for new paths
98 site_id
= (dbkey_t
) row
["site_id"];
101 // look for the mac addresses in the database, get mote_id
103 query
<< "select mote_id from moteattr ma, mote_moteattr mma, moteattrtype mat"
104 " where ma.val=" << mysqlpp::quote
<< mac
105 << " and mma.moteattr_id=ma.id"
106 " and ma.moteattrtype_id=mat.id"
107 " and mat.name='macaddress'";
110 selectRes
= query
.use();
111 selectRes
.disable_exceptions();
112 row
= selectRes
.fetch_row();
114 MoteAddresses
*newtarget
= new MoteAddresses(mac
);
116 if ( !row
|| row
.empty() )
118 std::ostringstream oss
;
121 // create the mote using site_id only - the mote class will create the
122 // mote database record itself
123 mote
= new Mote(site_id
,(MoteControlInfrastructure
&)*this,*newtarget
);
124 // TODO: error checking
125 // create the mac and net address database records using the mote id
126 oss
<< (uint16_t) mote
->mote_id
;
127 newtarget
->netAddress
= oss
.str();
129 Log::info("Attributes: macaddress=%s netaddress=%s platform=%s\n",
130 mac
.c_str(), newtarget
->netAddress
.c_str(),
131 info
.getPlatform().c_str());
132 mote
->setAttribute("macaddress", mac
);
133 mote
->setAttribute("netaddress", newtarget
->netAddress
);
134 mote
->setAttribute("platform", info
.getPlatform());
138 mote_id
= (dbkey_t
) row
["mote_id"]; // save the mote_id
140 // create the mote object using mote_id and site_id - the mote class will
141 // update the mote database record to reflect the new site
142 mote
= new Mote(mote_id
,site_id
,(MoteControlInfrastructure
&)*this,*newtarget
);
144 // get the net address mote attribute
145 newtarget
->netAddress
= mote
->getAttribute("netaddress");
146 // TODO: error checking
151 // finally, register the new mote in the local map
152 registerMoteByMac(mac
, mote
);
156 void Host::handleMotesLostList(MsgMoteConnectionInfoList
& infolist
)
158 MsgMoteConnectionInfo info
;
160 while (infolist
.getNextMoteInfo(info
))
161 deleteMoteByMac(info
.getMac());
164 void Host::handleMotesFoundList(MsgMoteConnectionInfoList
& infolist
)
166 MsgMoteConnectionInfo info
;
168 while (infolist
.getNextMoteInfo(info
)) {
169 findOrCreateMote(info
);
173 void Host::request(MCIAddress
& address
, MsgPayload
& request
)
175 MsgMoteAddresses
addresses(((MoteAddresses
&)address
).mac
,
176 ((MoteAddresses
&)address
).netAddress
);
177 MsgHostRequest
msgHostRequest(addresses
,request
);
178 HostMsg
message(msgHostRequest
);
182 msg
.sendMsg(fd
,message
);
184 catch (remote::protocols::MMSException e
)
186 Log::error("Exception: %s", e
.what());
192 void Host::handleEvent(short events
)
195 if ( (events
& POLLIN
) || (events
& POLLPRI
) )
197 if (!message_in
.nonBlockingRecv(fd
))
202 uint32_t msglen
= message_in
.getLength();
203 uint8_t* buffer
= message_in
.getData();
204 HostMsg
message(buffer
,msglen
);
206 switch (message
.getType())
208 case HOSTMSGTYPE_HOSTCONFIRM
:
209 handleMsgIn(message
.getHostConfirm());
211 case HOSTMSGTYPE_PLUGEVENT
:
212 if ( message
.getPlugEvent().getType() == PLUG_MOTES
)
214 handleMotesFoundList(message
.getPlugEvent().getInfoList());
216 else if ( message
.getPlugEvent().getType() == UNPLUG_MOTES
)
218 handleMotesLostList(message
.getPlugEvent().getInfoList());
222 __THROW__ ("Invalid plugevent received from host!");
226 __THROW__ ("Invalid message type received from host!");
230 else if ( (events
& POLLERR
) || (events
& POLLHUP
) || (events
& POLLNVAL
) )
232 __THROW__ ("Host connection error!\n");
236 void Host::handleMsgIn(MsgHostConfirm
& msgHostConfirm
)
238 motemapbymac_t::iterator mI
;
240 mI
= motesByMac
.find(msgHostConfirm
.getMoteAddresses().getMac());
241 if (mI
!= motesByMac
.end()) {
242 if (msgHostConfirm
.getStatus() == MSGHOSTCONFIRM_UNKNOWN_MOTE
) {
243 deleteMoteByMac(msgHostConfirm
.getMoteAddresses().getMac());
245 mI
->second
->confirm(msgHostConfirm
.getMessage());