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
)
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);
17 log("Closing host %s!\n",ipaddress
.c_str());
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
);
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
;
50 mI
= motesByMac
.find(mac
);
52 if ( mI
!= motesByMac
.end() )
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
;
71 mysqlpp::ResUse selectRes
;
72 mysqlpp::ResNSel execRes
;
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
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
99 site_id
= (dbkey_t
) row
["site_id"];
102 // look for the mac addresses in the database, get mote_id
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'";
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
;
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());
139 mote_id
= (dbkey_t
) row
["mote_id"]; // save the mote_id
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
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
);
183 msg
.sendMsg(fd
,message
);
185 catch (remote::protocols::MMSException e
)
187 log("Exception: %s\n",e
.what());
193 void Host::handleEvent(short events
)
196 if ( (events
& POLLIN
) || (events
& POLLPRI
) )
198 if (!message_in
.nonBlockingRecv(fd
))
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());
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());
223 __THROW__ ("Invalid plugevent received from host!");
227 __THROW__ ("Invalid message type received from host!");
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());
246 mI
->second
->confirm(msgHostConfirm
.getMessage());