diff --git a/src/ifmap/ifmap_client.cc b/src/ifmap/ifmap_client.cc index 01cd426dd13..81dfd8417f1 100644 --- a/src/ifmap/ifmap_client.cc +++ b/src/ifmap/ifmap_client.cc @@ -32,45 +32,3 @@ std::vector IFMapClient::vm_list() const { return vm_list; } -void IFMapClient::ConfigTrackerAdd(IFMapState *state) { - config_tracker_.insert(state); -} - -void IFMapClient::ConfigTrackerDelete(IFMapState *state) { - CtSz_t num = config_tracker_.erase(state); - assert(num == 1); -} - -bool IFMapClient::ConfigTrackerHasState(IFMapState *state) { - ConfigTracker::iterator iter = config_tracker_.find(state); - return (iter == config_tracker_.end() ? false : true); -} - -bool IFMapClient::ConfigTrackerEmpty() { - return config_tracker_.empty(); -} - -size_t IFMapClient::ConfigTrackerSize() { - return config_tracker_.size(); -} - -void IFMapClient::ConfigDbCleanup() { - BitSet rm_bs; - rm_bs.set(index_); - - for (ConfigTracker::iterator iter = config_tracker_.begin(); - iter != config_tracker_.end(); ++iter) { - IFMapState *state = *iter; - state->InterestReset(rm_bs); - state->AdvertisedReset(rm_bs); - } - config_tracker_.clear(); -} - -void IFMapClient::ResetLinkDeleteClients() { - BitSet rm_bs; - rm_bs.set(index_); - - exporter_->ResetLinkDeleteClients(rm_bs); -} - diff --git a/src/ifmap/ifmap_client.h b/src/ifmap/ifmap_client.h index f659c9952b8..610591fb651 100644 --- a/src/ifmap/ifmap_client.h +++ b/src/ifmap/ifmap_client.h @@ -18,8 +18,6 @@ class IFMapState; class IFMapClient { public: typedef std::map VmMap; - typedef boost::unordered_set ConfigTracker; - typedef ConfigTracker::size_type CtSz_t; static const int kIndexInvalid = -1; IFMapClient(); @@ -68,14 +66,6 @@ class IFMapClient { // return vm_map_ as a list of strings std::vector vm_list() const; - void ConfigTrackerAdd(IFMapState *state); - void ConfigTrackerDelete(IFMapState *state); - bool ConfigTrackerHasState(IFMapState *state); - bool ConfigTrackerEmpty(); - size_t ConfigTrackerSize(); - void ConfigDbCleanup(); - void ResetLinkDeleteClients(); - private: int index_; IFMapExporter *exporter_; @@ -87,7 +77,6 @@ class IFMapClient { bool send_is_blocked_; VmMap vm_map_; std::string name_; - ConfigTracker config_tracker_; }; #endif diff --git a/src/ifmap/ifmap_exporter.cc b/src/ifmap/ifmap_exporter.cc index 237935b6570..7e1fd7fc1c5 100644 --- a/src/ifmap/ifmap_exporter.cc +++ b/src/ifmap/ifmap_exporter.cc @@ -67,6 +67,14 @@ void IFMapExporter::Initialize(DB *db) { } void IFMapExporter::Shutdown() { + for (size_t index = 0; index < client_config_tracker_.size(); ++index) { + ConfigSet *set = client_config_tracker_[index]; + if (set) { + set->clear(); + delete set; + client_config_tracker_[index] = NULL; + } + } for (TableMap::iterator iter = table_map_.begin(); iter != table_map_.end(); ++iter) { DBTable *table = iter->first; @@ -607,21 +615,73 @@ bool IFMapExporter::ConfigChanged(IFMapNode *node) { return changed; } +void IFMapExporter::AddClientConfigTracker(int index) { + if (index >= (int)client_config_tracker_.size()) { + client_config_tracker_.resize(index + 1, NULL); + } + assert(client_config_tracker_[index] == NULL); + ConfigSet *set = new ConfigSet(); + client_config_tracker_[index] = set; +} + +void IFMapExporter::DeleteClientConfigTracker(int index) { + ConfigSet *set = client_config_tracker_.at(index); + assert(set); + delete set; + client_config_tracker_[index] = NULL; +} + void IFMapExporter::UpdateClientConfigTracker(IFMapState *state, const BitSet& client_bits, bool add) { - IFMapClient *client = NULL; for (size_t pos = client_bits.find_first(); pos != BitSet::npos; pos = client_bits.find_next(pos)) { - client = server_->GetClient(pos); - assert(client); + ConfigSet *set = client_config_tracker_.at(pos); + assert(set); if (add) { - client->ConfigTrackerAdd(state); + set->insert(state); } else { - client->ConfigTrackerDelete(state); + CsSz_t num = set->erase(state); + assert(num == 1); } } } +void IFMapExporter::CleanupClientConfigTrackedEntries(int index) { + ConfigSet *set = client_config_tracker_.at(index); + assert(set); + BitSet rm_bs; + rm_bs.set(index); + for (ConfigSet::iterator iter = set->begin(); iter != set->end(); ++iter) { + IFMapState *state = *iter; + state->InterestReset(rm_bs); + state->AdvertisedReset(rm_bs); + } +} + +bool IFMapExporter::ClientHasConfigTracker(int index) { + ConfigSet *set = client_config_tracker_.at(index); + return ((set != NULL) ? true : false); +} + +bool IFMapExporter::ClientConfigTrackerHasState(int index, IFMapState *state) { + ConfigSet *set = client_config_tracker_.at(index); + assert(set); + ConfigSet::iterator iter = set->find(state); + return (iter == set->end() ? false : true); +} + +bool IFMapExporter::ClientConfigTrackerEmpty(int index) { + ConfigSet *set = client_config_tracker_.at(index); + assert(set); + return set->empty(); +} + +size_t IFMapExporter::ClientConfigTrackerSize(int index) { + ConfigSet *set = client_config_tracker_.at(index); + assert(set); + return set->size(); +} + void IFMapExporter::StateInterestSet(IFMapState *state, const BitSet& interest_bits) { // Add the node to the config-tracker of all clients that just became diff --git a/src/ifmap/ifmap_exporter.h b/src/ifmap/ifmap_exporter.h index b6c539bc538..fea5423c977 100644 --- a/src/ifmap/ifmap_exporter.h +++ b/src/ifmap/ifmap_exporter.h @@ -11,6 +11,7 @@ #include #include // for boost::crc_32_type #include +#include #include "db/db_table.h" @@ -39,6 +40,9 @@ struct IFMapTypenameWhiteList; // must come after the links that refer to the node have been deleted. class IFMapExporter { public: + typedef boost::unordered_set ConfigSet; + typedef ConfigSet::size_type CsSz_t; + typedef std::vector ClientConfigTracker; typedef boost::crc_32_type::value_type crc32type; explicit IFMapExporter(IFMapServer *server); ~IFMapExporter(); @@ -61,8 +65,16 @@ class IFMapExporter { bool FilterNeighbor(IFMapNode *lnode, IFMapNode *rnode); + void AddClientConfigTracker(int index); + void DeleteClientConfigTracker(int index); void UpdateClientConfigTracker(IFMapState *state, const BitSet& client_bits, bool add); + void CleanupClientConfigTrackedEntries(int index); + bool ClientHasConfigTracker(int index); + bool ClientConfigTrackerHasState(int index, IFMapState *state); + bool ClientConfigTrackerEmpty(int index); + size_t ClientConfigTrackerSize(int index); + void StateInterestSet(IFMapState *state, const BitSet& interest_bits); void StateInterestOr(IFMapState *state, const BitSet& interest_bits); void StateInterestReset(IFMapState *state, const BitSet& interest_bits); @@ -113,6 +125,7 @@ class IFMapExporter { TableMap table_map_; DBTable *link_table_; + ClientConfigTracker client_config_tracker_; }; #endif diff --git a/src/ifmap/ifmap_server.cc b/src/ifmap/ifmap_server.cc index fc5343ca317..112e77b46cd 100644 --- a/src/ifmap/ifmap_server.cc +++ b/src/ifmap/ifmap_server.cc @@ -238,9 +238,9 @@ void IFMapServer::ClientUnregister(IFMapClient *client) { bool IFMapServer::ProcessClientWork(bool add, IFMapClient *client) { if (add) { ClientRegister(client); + ClientExporterSetup(client); ClientGraphDownload(client); } else { - ClientConfigDbCleanup(client); RemoveSelfAddedLinksAndObjects(client); CleanupUuidMapper(client); ClientExporterCleanup(client); @@ -334,12 +334,17 @@ void IFMapServer::ClientGraphDownload(IFMapClient *client) { } } -void IFMapServer::ClientConfigDbCleanup(IFMapClient *client) { - client->ConfigDbCleanup(); +void IFMapServer::ClientExporterSetup(IFMapClient *client) { + exporter_->AddClientConfigTracker(client->index()); } void IFMapServer::ClientExporterCleanup(IFMapClient *client) { - client->ResetLinkDeleteClients(); + exporter_->CleanupClientConfigTrackedEntries(client->index()); + exporter_->DeleteClientConfigTracker(client->index()); + + BitSet rm_bs; + rm_bs.set(client->index()); + exporter_->ResetLinkDeleteClients(rm_bs); } IFMapClient *IFMapServer::FindClient(const std::string &id) { diff --git a/src/ifmap/ifmap_server.h b/src/ifmap/ifmap_server.h index 9aea3a2eaf3..6427de9d79a 100644 --- a/src/ifmap/ifmap_server.h +++ b/src/ifmap/ifmap_server.h @@ -105,6 +105,7 @@ class IFMapServer { friend class IFMapRestartTest; friend class ShowIFMapXmppClientInfo; friend class XmppIfmapTest; + friend class IFMapExporterTest; enum QueueOp { ADD = 1, @@ -116,9 +117,9 @@ class IFMapServer { }; bool ClientWorker(QueueEntry work_entry); void ClientGraphDownload(IFMapClient *client); - void ClientConfigDbCleanup(IFMapClient *client); void RemoveSelfAddedLinksAndObjects(IFMapClient *client); void CleanupUuidMapper(IFMapClient *client); + void ClientExporterSetup(IFMapClient *client); void ClientExporterCleanup(IFMapClient *client); bool StaleNodesProcTimeout(); const ClientMap &GetClientMap() const { return client_map_; } diff --git a/src/ifmap/ifmap_server_show.cc b/src/ifmap/ifmap_server_show.cc index 510e421bbdd..a6bde5ff01c 100644 --- a/src/ifmap/ifmap_server_show.cc +++ b/src/ifmap/ifmap_server_show.cc @@ -878,15 +878,15 @@ bool ShowIFMapPerClientNodes::CopyNode(IFMapPerClientNodesShowInfo *dest, } else { dest->sent = "No"; } - IFMapClient *client = server->GetClient(client_index); - if (client) { - if (client->ConfigTrackerHasState(state)) { + if (server->exporter()->ClientHasConfigTracker(client_index)) { + if (server->exporter()->ClientConfigTrackerHasState(client_index, + state)) { dest->tracked = "Yes"; } else { dest->tracked = "No"; } } else { - dest->tracked = "Client unknown"; + dest->tracked = "No tracker"; } return true; } else { @@ -1070,15 +1070,15 @@ bool ShowIFMapPerClientLinkTable::CopyNode(IFMapPerClientLinksShowInfo *dest, } else { dest->sent = "No"; } - IFMapClient *client = server->GetClient(client_index); - if (client) { - if (client->ConfigTrackerHasState(state)) { + if (server->exporter()->ClientHasConfigTracker(client_index)) { + if (server->exporter()->ClientConfigTrackerHasState(client_index, + state)) { dest->tracked = "Yes"; } else { dest->tracked = "No"; } } else { - dest->tracked = "Client unknown"; + dest->tracked = "No tracker"; } return true; } else { diff --git a/src/ifmap/test/ifmap_exporter_test.cc b/src/ifmap/test/ifmap_exporter_test.cc index ff1ea6950e2..b7bb08261d8 100644 --- a/src/ifmap/test/ifmap_exporter_test.cc +++ b/src/ifmap/test/ifmap_exporter_test.cc @@ -165,6 +165,23 @@ class IFMapExporterTest : public ::testing::Test { } } + void ClientSetup(IFMapClient *client) { + server_.ClientRegister(client); + server_.ClientExporterSetup(client); + } + + bool ClientConfigTrackerHasState(int index, IFMapState *state) { + return exporter_->ClientConfigTrackerHasState(index, state); + } + + bool ClientConfigTrackerEmpty(int index) { + return exporter_->ClientConfigTrackerEmpty(index); + } + + size_t ClientConfigTrackerSize(int index) { + return exporter_->ClientConfigTrackerSize(index); + } + DB db_; DBGraph graph_; EventManager evm_; @@ -183,7 +200,7 @@ static string FileRead(const string &filename) { TEST_F(IFMapExporterTest, Basic) { server_.SetSender(new IFMapUpdateSenderMock(&server_)); TestClient c1("192.168.1.1"); - server_.ClientRegister(&c1); + ClientSetup(&c1); IFMapMsgLink("domain", "project", "user1", "vnc"); IFMapMsgLink("project", "virtual-network", "vnc", "blue"); @@ -234,10 +251,10 @@ TEST_F(IFMapExporterTest, InterestChangeIntersect) { TestClient c3("192.168.1.3"); TestClient c4("192.168.1.4"); - server_.ClientRegister(&c1); - server_.ClientRegister(&c2); - server_.ClientRegister(&c3); - server_.ClientRegister(&c4); + ClientSetup(&c1); + ClientSetup(&c2); + ClientSetup(&c3); + ClientSetup(&c4); IFMapMsgLink("domain", "project", "user1", "vnc"); IFMapMsgLink("project", "virtual-network", "vnc", "blue"); @@ -371,7 +388,7 @@ TEST_F(IFMapExporterTest, InterestChangeIntersect) { TEST_F(IFMapExporterTest, NodeAddDependency) { server_.SetSender(new IFMapUpdateSenderMock(&server_)); TestClient c1("192.168.1.1"); - server_.ClientRegister(&c1); + ClientSetup(&c1); IFMapMsgLink("domain", "project", "user1", "vnc"); IFMapMsgLink("project", "virtual-network", "vnc", "blue"); @@ -411,7 +428,7 @@ TEST_F(IFMapExporterTest, NodeAddDependency) { TEST_F(IFMapExporterTest, LinkDeleteDependency) { server_.SetSender(new IFMapUpdateSenderMock(&server_)); TestClient c1("192.168.1.1"); - server_.ClientRegister(&c1); + ClientSetup(&c1); IFMapMsgLink("domain", "project", "user1", "vnc"); IFMapMsgLink("project", "virtual-network", "vnc", "blue"); @@ -618,7 +635,7 @@ TEST_F(IFMapExporterTest, CrcChecks) { TEST_F(IFMapExporterTest, ChangePropertiesIncrementally) { server_.SetSender(new IFMapUpdateSenderMock(&server_)); TestClient c1("vr-test"); - server_.ClientRegister(&c1); + ClientSetup(&c1); IFMapMsgLink("domain", "project", "user1", "vnc"); IFMapMsgLink("project", "virtual-network", "vnc", "blue"); @@ -822,7 +839,7 @@ TEST_F(IFMapExporterTest, PR1383393) { TEST_F(IFMapExporterTest, PR1454380) { server_.SetSender(new IFMapUpdateSenderMock(&server_)); TestClient c1("vr-test"); - server_.ClientRegister(&c1); + ClientSetup(&c1); IFMapMsgLink("domain", "project", "user1", "vnc"); IFMapMsgLink("project", "virtual-network", "vnc", "blue"); @@ -917,10 +934,10 @@ TEST_F(IFMapExporterTest, ConfigTracker) { TestClient c3("192.168.1.3"); TestClient c4("192.168.1.4"); - server_.ClientRegister(&c1); - server_.ClientRegister(&c2); - server_.ClientRegister(&c3); - server_.ClientRegister(&c4); + ClientSetup(&c1); + ClientSetup(&c2); + ClientSetup(&c3); + ClientSetup(&c4); IFMapMsgLink("domain", "project", "user1", "vnc"); IFMapMsgLink("project", "virtual-network", "vnc", "blue"); @@ -947,10 +964,10 @@ TEST_F(IFMapExporterTest, ConfigTracker) { task_util::WaitForIdle(); TASK_UTIL_EXPECT_EQ(LinkTableSize(), 10); - EXPECT_TRUE(c1.ConfigTrackerEmpty()); - EXPECT_TRUE(c2.ConfigTrackerEmpty()); - EXPECT_TRUE(c3.ConfigTrackerEmpty()); - EXPECT_TRUE(c4.ConfigTrackerEmpty()); + EXPECT_TRUE(ClientConfigTrackerEmpty(c1.index())); + EXPECT_TRUE(ClientConfigTrackerEmpty(c2.index())); + EXPECT_TRUE(ClientConfigTrackerEmpty(c3.index())); + EXPECT_TRUE(ClientConfigTrackerEmpty(c4.index())); // Add the vr-vm link for c1. The state for VN 'blue' must have c1. IFMapMsgLink("virtual-router", "virtual-machine", "192.168.1.1", "vm_c1"); @@ -963,25 +980,25 @@ TEST_F(IFMapExporterTest, ConfigTracker) { IFMapNodeState *state = exporter_->NodeStateLookup(blue); ASSERT_TRUE(state != NULL); TASK_UTIL_EXPECT_TRUE(state->interest().test(c1.index())); - TASK_UTIL_EXPECT_TRUE(c1.ConfigTrackerHasState(state)); + TASK_UTIL_EXPECT_TRUE(ClientConfigTrackerHasState(c1.index(), state)); // Add the vr-vm link for c2. The state for VN 'blue' must have c2. IFMapMsgLink("virtual-router", "virtual-machine", "192.168.1.2", "vm_c2"); task_util::WaitForIdle(); TASK_UTIL_EXPECT_TRUE(state->interest().test(c2.index())); - TASK_UTIL_EXPECT_TRUE(c2.ConfigTrackerHasState(state)); + TASK_UTIL_EXPECT_TRUE(ClientConfigTrackerHasState(c2.index(), state)); // Add the vr-vm link for c3. The state for VN 'blue' must have c3. IFMapMsgLink("virtual-router", "virtual-machine", "192.168.1.3", "vm_c3"); task_util::WaitForIdle(); TASK_UTIL_EXPECT_TRUE(state->interest().test(c3.index())); - TASK_UTIL_EXPECT_TRUE(c3.ConfigTrackerHasState(state)); + TASK_UTIL_EXPECT_TRUE(ClientConfigTrackerHasState(c3.index(), state)); // Add the vr-vm link for c4. The state for VN 'blue' must have c4. IFMapMsgLink("virtual-router", "virtual-machine", "192.168.1.4", "vm_c4"); task_util::WaitForIdle(); TASK_UTIL_EXPECT_TRUE(state->interest().test(c4.index())); - TASK_UTIL_EXPECT_TRUE(c4.ConfigTrackerHasState(state)); + TASK_UTIL_EXPECT_TRUE(ClientConfigTrackerHasState(c4.index(), state)); // Check if all the bits are set for VN 'blue' and all the clients have // 'blue' in their config-tracker. @@ -989,51 +1006,57 @@ TEST_F(IFMapExporterTest, ConfigTracker) { EXPECT_TRUE(state->interest().test(c2.index())); EXPECT_TRUE(state->interest().test(c3.index())); EXPECT_TRUE(state->interest().test(c4.index())); - EXPECT_TRUE(c1.ConfigTrackerHasState(state)); - EXPECT_TRUE(c2.ConfigTrackerHasState(state)); - EXPECT_TRUE(c3.ConfigTrackerHasState(state)); - EXPECT_TRUE(c4.ConfigTrackerHasState(state)); + EXPECT_TRUE(ClientConfigTrackerHasState(c1.index(), state)); + EXPECT_TRUE(ClientConfigTrackerHasState(c2.index(), state)); + EXPECT_TRUE(ClientConfigTrackerHasState(c3.index(), state)); + EXPECT_TRUE(ClientConfigTrackerHasState(c4.index(), state)); // VR, VM, VMI, VN, VR-VM, VM-VMI, VMI-VN i.e. 7 - EXPECT_EQ(c1.ConfigTrackerSize(), 7); - EXPECT_EQ(c2.ConfigTrackerSize(), 7); - EXPECT_EQ(c3.ConfigTrackerSize(), 7); - EXPECT_EQ(c4.ConfigTrackerSize(), 7); + EXPECT_EQ(ClientConfigTrackerSize(c1.index()), 7); + EXPECT_EQ(ClientConfigTrackerSize(c2.index()), 7); + EXPECT_EQ(ClientConfigTrackerSize(c3.index()), 7); + EXPECT_EQ(ClientConfigTrackerSize(c4.index()), 7); ProcessQueue(); task_util::WaitForIdle(); + // 10 from before and 4 new VR-VM links. + TASK_UTIL_EXPECT_EQ(LinkTableSize(), 14); + // Remove the vr-vm link for c1. IFMapMsgUnlink("virtual-router", "virtual-machine", "192.168.1.1", "vm_c1"); task_util::WaitForIdle(); TASK_UTIL_EXPECT_FALSE(state->interest().test(c1.index())); - TASK_UTIL_EXPECT_FALSE(c1.ConfigTrackerHasState(state)); + TASK_UTIL_EXPECT_FALSE(ClientConfigTrackerHasState(c1.index(), state)); // Remove the vr-vm link for c2. IFMapMsgUnlink("virtual-router", "virtual-machine", "192.168.1.2", "vm_c2"); task_util::WaitForIdle(); TASK_UTIL_EXPECT_FALSE(state->interest().test(c2.index())); - TASK_UTIL_EXPECT_FALSE(c2.ConfigTrackerHasState(state)); + TASK_UTIL_EXPECT_FALSE(ClientConfigTrackerHasState(c2.index(), state)); // Remove the vr-vm link for c3. IFMapMsgUnlink("virtual-router", "virtual-machine", "192.168.1.3", "vm_c3"); task_util::WaitForIdle(); TASK_UTIL_EXPECT_FALSE(state->interest().test(c3.index())); - TASK_UTIL_EXPECT_FALSE(c3.ConfigTrackerHasState(state)); + TASK_UTIL_EXPECT_FALSE(ClientConfigTrackerHasState(c3.index(), state)); // Remove the vr-vm link for c4. IFMapMsgUnlink("virtual-router", "virtual-machine", "192.168.1.4", "vm_c4"); task_util::WaitForIdle(); TASK_UTIL_EXPECT_FALSE(state->interest().test(c4.index())); - TASK_UTIL_EXPECT_FALSE(c4.ConfigTrackerHasState(state)); + TASK_UTIL_EXPECT_FALSE(ClientConfigTrackerHasState(c4.index(), state)); // The config-tracker must be empty for all clients. EXPECT_TRUE(state->interest().empty()); - EXPECT_TRUE(c1.ConfigTrackerEmpty()); - EXPECT_TRUE(c2.ConfigTrackerEmpty()); - EXPECT_TRUE(c3.ConfigTrackerEmpty()); - EXPECT_TRUE(c4.ConfigTrackerEmpty()); + EXPECT_TRUE(ClientConfigTrackerEmpty(c1.index())); + EXPECT_TRUE(ClientConfigTrackerEmpty(c2.index())); + EXPECT_TRUE(ClientConfigTrackerEmpty(c3.index())); + EXPECT_TRUE(ClientConfigTrackerEmpty(c4.index())); ProcessQueue(); + task_util::WaitForIdle(); + // The 4 VR-VM links have been deleted. + TASK_UTIL_EXPECT_EQ(LinkTableSize(), 10); } int main(int argc, char **argv) { diff --git a/src/ifmap/test/ifmap_xmpp_test.cc b/src/ifmap/test/ifmap_xmpp_test.cc index 587cf5596c0..745eff28f84 100644 --- a/src/ifmap/test/ifmap_xmpp_test.cc +++ b/src/ifmap/test/ifmap_xmpp_test.cc @@ -574,6 +574,10 @@ class XmppIfmapTest : public ::testing::Test { exporter_->LinkTableExport(partition, link); } + size_t ClientConfigTrackerSize(int index) { + return exporter_->ClientConfigTrackerSize(index); + } + DB db_; DBGraph graph_; EventManager evm_; @@ -1722,8 +1726,8 @@ TEST_F(XmppIfmapTest, Cli1Vn1Vm3Add) { TASK_UTIL_EXPECT_EQ(client->msgs_sent(), vnsw_client->Count()); size_t cli_index = static_cast(client->index()); int walk_count = ClientGraphWalkVerify(client_name, cli_index, true, true); - EXPECT_EQ(client->ConfigTrackerSize(), walk_count); - EXPECT_EQ(client->ConfigTrackerSize(), 32); + EXPECT_EQ(ClientConfigTrackerSize(client->index()), walk_count); + EXPECT_EQ(ClientConfigTrackerSize(client->index()), 32); EXPECT_EQ(ifmap_server_.GetClientMapSize(), 1); // client close generates a TcpClose event on server