From 4c3a537ab998d02d33f4335aae0e5da89da22d5e Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Sat, 7 Mar 2015 13:30:07 +0530 Subject: [PATCH] Invoke RetryDelete() on unregister of last listener The lifetime actors for route db-tables will wait till number of entries in dbtable is 0 and there are no listeners to the table. DBTable infrastructure invokes RetryDelete() when a DBTablePartition becomes empty. In addition, it should invoke RetryDelete() when all db-table listeners are gone also. The fix will invoke RetryDelete() when number of listeners becomes empty Change-Id: I659a07bde0b790be08b5cafe1349c3c6b640d1ec Closes-Bug: #1429348 --- src/db/db_table.cc | 4 ++++ src/db/db_table.h | 6 +++--- src/db/test/db_base_test.cc | 6 ++++++ src/db/test/db_test.cc | 12 ++++++++++-- src/db/test/db_test_cmn.h | 10 ++++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/db/db_table.cc b/src/db/db_table.cc index e110477ac20..0c9bb9782b1 100644 --- a/src/db/db_table.cc +++ b/src/db/db_table.cc @@ -114,6 +114,10 @@ DBTableBase::ListenerId DBTableBase::Register(ChangeCallback callback) { void DBTableBase::Unregister(ListenerId listener) { info_->Unregister(listener); + // If a table is marked for deletion, then we may trigger the deletion + // process when the last client is removed + if (info_->empty()) + RetryDelete(); } bool DBTableBase::Enqueue(DBRequest *req) { diff --git a/src/db/db_table.h b/src/db/db_table.h index 8905699bbae..6a42d851bd7 100644 --- a/src/db/db_table.h +++ b/src/db/db_table.h @@ -81,6 +81,9 @@ class DBTableBase { // Calculate the size across all partitions. virtual size_t Size() const { return 0; } + // Suspended deletion resume hook for user function + virtual void RetryDelete() { } + DB *database() { return db_; } const DB *database() const { return db_; } @@ -143,9 +146,6 @@ class DBTable : public DBTableBase { // Delete hook for user function virtual bool Delete(DBEntry *entry, const DBRequest *req); - // Suspended deletion resume hook for user function - virtual void RetryDelete() { } - void WalkCompleteCallback(DBTableBase *tbl_base); void NotifyAllEntries(); diff --git a/src/db/test/db_base_test.cc b/src/db/test/db_base_test.cc index c2f749d72b6..9089b1a7501 100644 --- a/src/db/test/db_base_test.cc +++ b/src/db/test/db_base_test.cc @@ -223,7 +223,13 @@ class VlanTable : public DBTableBase { return table; } + void RetryDelete() { + retry_delete_count_++; + } + + uint32_t retry_delete_count() const { return retry_delete_count_; } private: + uint32_t retry_delete_count_; std::vector partitions_; DISALLOW_COPY_AND_ASSIGN(VlanTable); }; diff --git a/src/db/test/db_test.cc b/src/db/test/db_test.cc index 07cc377b48d..a85ec1476b8 100644 --- a/src/db/test/db_test.cc +++ b/src/db/test/db_test.cc @@ -79,8 +79,10 @@ class Vlan : public DBEntry { class VlanTable : public DBTable { public: - VlanTable(DB *db) : DBTable(db, "__vlan__.0") { }; - ~VlanTable() { }; + VlanTable(DB *db) : + DBTable(db, "__vlan__.0"), retry_delete_count_(0), del_req_count_(0) { + } + ~VlanTable() { } uint32_t del_req_count() const { return del_req_count_; } @@ -136,6 +138,12 @@ class VlanTable : public DBTable { return table; } + void RetryDelete() { + retry_delete_count_++; + } + + uint32_t retry_delete_count() const { return retry_delete_count_; } + uint32_t retry_delete_count_; uint32_t del_req_count_; DISALLOW_COPY_AND_ASSIGN(VlanTable); }; diff --git a/src/db/test/db_test_cmn.h b/src/db/test/db_test_cmn.h index 1e975e701f7..89c46dcda95 100644 --- a/src/db/test/db_test_cmn.h +++ b/src/db/test/db_test_cmn.h @@ -151,12 +151,15 @@ class DBTest : public ::testing::Test { TEST_F(DBTest, Basic) { EXPECT_EQ(itbl, db_.FindTable("db.test.vlan.0")); + uint32_t retry_delete_count = itbl->retry_delete_count(); tid_ = itbl->Register(boost::bind(&DBTest::DBTestListener, this, _1, _2)); EXPECT_EQ(tid_, 0); itbl->Unregister(tid_); + EXPECT_EQ(itbl->retry_delete_count(), retry_delete_count+1); + retry_delete_count = itbl->retry_delete_count(); for (int i = 0; i < 15; i++) { tid_ = @@ -166,6 +169,8 @@ TEST_F(DBTest, Basic) { } itbl->Unregister(7); + // There are pending registers. retry_delete_count is not incremented + EXPECT_EQ(itbl->retry_delete_count(), retry_delete_count); tid_ = itbl->Register(boost::bind(&DBTest::DBTestListener, this, _1, _2)); @@ -173,8 +178,13 @@ TEST_F(DBTest, Basic) { for (int i = 14; i >=0; i--) { + EXPECT_EQ(itbl->retry_delete_count(), retry_delete_count); itbl->Unregister(i); } + + // All clients are registered. retry_delete_count should be incremented + EXPECT_EQ(itbl->retry_delete_count(), retry_delete_count+1); + retry_delete_count = itbl->retry_delete_count(); } // To Test: