Introduce `RefCounter` class to remove duplicated code in LogClient
and LogStreamInfo.
Introduce also one new parameter `caller`, the purpose is mainly
for debug - know who is the caller to `RefCounter` methods.
---
src/log/Makefile.am | 5 +-
src/log/agent/lga_agent.cc | 82 +++++++++++++++------------
src/log/agent/lga_client.cc | 62 ++++-----------------
src/log/agent/lga_client.h | 45 ++++++++-------
src/log/agent/lga_common.h | 8 ---
src/log/agent/lga_mds.cc | 7 +--
src/log/agent/lga_ref_counter.cc | 73 ++++++++++++++++++++++++
src/log/agent/lga_ref_counter.h | 117 +++++++++++++++++++++++++++++++++++++++
src/log/agent/lga_stream.cc | 46 +--------------
src/log/agent/lga_stream.h | 40 ++++++-------
10 files changed, 300 insertions(+), 185 deletions(-)
create mode 100644 src/log/agent/lga_ref_counter.cc
create mode 100644 src/log/agent/lga_ref_counter.h
diff --git a/src/log/Makefile.am b/src/log/Makefile.am
index b66b8a7..3d951eb 100644
--- a/src/log/Makefile.am
+++ b/src/log/Makefile.am
@@ -31,7 +31,9 @@ lib_libSaLog_la_SOURCES = \
src/log/agent/lga_util.cc \
src/log/agent/lga_mds.cc \
src/log/agent/lga_state.cc \
- src/log/agent/lga_agent.cc
+ src/log/agent/lga_agent.cc \
+ src/log/agent/lga_ref_counter.cc
+
nodist_EXTRA_lib_libSaLog_la_SOURCES = dummy.cc
@@ -66,6 +68,7 @@ noinst_HEADERS += \
src/log/agent/lga_agent.h \
src/log/agent/lga_stream.h \
src/log/agent/lga_state.h \
+ src/log/agent/lga_ref_counter.h \
src/log/common/lgsv_defs.h \
src/log/common/lgsv_msg.h \
src/log/logd/lgs.h \
diff --git a/src/log/agent/lga_agent.cc b/src/log/agent/lga_agent.cc
index 55ee916..042bde3 100644
--- a/src/log/agent/lga_agent.cc
+++ b/src/log/agent/lga_agent.cc
@@ -56,7 +56,9 @@ class ScopeData {
bool* is_updated;
// The increased value if @is_updated set. The aim of using enum instead
// of `int` type is to force the caller pass either value (1) or value
(-1).
- RefCounterDegree value;
+ RefCounter::Degree value;
+ // Who is the caller of `RestoreRefCounter`
+ const char* caller;
};
struct LogStreamInfoData {
@@ -66,7 +68,9 @@ class ScopeData {
bool* is_updated;
// The increased value if @is_updated set. The aim of using enum instead
// of `int` type is to force the caller pass either value (1) or value
(-1).
- RefCounterDegree value;
+ RefCounter::Degree value;
+ // Who is the caller of `RestoreRefCounter`
+ const char* caller;
};
explicit ScopeData(LogClientData*, bool* lock = nullptr);
@@ -107,20 +111,23 @@ ScopeData::~ScopeData() {
LogAgent::instance().EnterCriticalSection();
LogClient* client = client_data_->client;
bool* is_updated = client_data_->is_updated;
- RefCounterDegree client_degree = client_data_->value;
+ RefCounter::Degree client_degree = client_data_->value;
+ const char* caller = client_data_->caller;
if (client != nullptr) {
// Do restore the reference counter if the client exists.
- client->RestoreRefCounter(client_degree, *is_updated);
- if (stream_data_ != nullptr) {
- LogStreamInfo* stream = stream_data_->stream;
- bool* stream_is_updated = stream_data_->is_updated;
- RefCounterDegree stream_degree = stream_data_->value;
- if (stream != nullptr) {
- // Do restore the reference counter if the stream exists.
- stream->RestoreRefCounter(stream_degree, *stream_is_updated);
- }
- } // stream_data_
- } // client
+ client->RestoreRefCounter(caller, client_degree, *is_updated);
+ }
+
+ if (stream_data_ != nullptr) {
+ LogStreamInfo* stream = stream_data_->stream;
+ bool* stream_is_updated = stream_data_->is_updated;
+ RefCounter::Degree stream_degree = stream_data_->value;
+ const char* caller = stream_data_->caller;
+ if (stream != nullptr) {
+ // Do restore the reference counter if the stream exists.
+ stream->RestoreRefCounter(caller, stream_degree, *stream_is_updated);
+ }
+ }
LogAgent::instance().LeaveCriticalSection();
}
@@ -137,13 +144,20 @@ LogAgent::LogAgent() {
// even they are in the same thread context.
// To avoid such risk, use RECURSIVE MUTEX for @LogClient
pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&mutex_, nullptr);
+ int result = pthread_mutexattr_init(&attr);
+ assert(result == 0 && "Failed to init mutex attribute");
+
+ result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ assert(result == 0 && "Failed to set mutex type");
+
+ result = pthread_mutex_init(&mutex_, nullptr);
+ assert(result == 0 && "Failed to init `mutex_`");
+
pthread_mutexattr_destroy(&attr);
// Initialize @get_delete_obj_sync_mutex_
- pthread_mutex_init(&get_delete_obj_sync_mutex_, nullptr);
+ result = pthread_mutex_init(&get_delete_obj_sync_mutex_, nullptr);
+ assert(result == 0 && "Failed to init `get_delete_obj_sync_mutex_`");
}
void LogAgent::PopulateOpenParams(
@@ -419,7 +433,7 @@ SaAisErrorT LogAgent::saLogSelectionObjectGet(
// such as Restore the reference counter after fetching & updating.
// or unlock recovery mutex.
ScopeData::LogClientData client_data{client, &updated,
- RefCounterDegree::kIncOne};
+ RefCounter::Degree::kIncOne, __func__};
ScopeData data{&client_data};
if (selectionObject == nullptr) {
@@ -439,7 +453,7 @@ SaAisErrorT LogAgent::saLogSelectionObjectGet(
return ais_rc;
}
- if (client->FetchAndIncreaseRefCounter(&updated) == -1) {
+ if (client->FetchAndIncreaseRefCounter(__func__, &updated) == -1) {
// @client is being deleted. Don't touch @this client
ais_rc = SA_AIS_ERR_TRY_AGAIN;
return ais_rc;
@@ -470,7 +484,7 @@ SaAisErrorT LogAgent::saLogDispatch(SaLogHandleT logHandle,
// such as Restore the reference counter fetching & updating.
// or unlock recovery mutex.
ScopeData::LogClientData client_data{client, &updated,
- RefCounterDegree::kIncOne};
+ RefCounter::Degree::kIncOne, __func__};
ScopeData data{&client_data};
if (is_dispatch_flag_valid(dispatchFlags) == false) {
@@ -490,7 +504,7 @@ SaAisErrorT LogAgent::saLogDispatch(SaLogHandleT logHandle,
return ais_rc;
}
- if (client->FetchAndIncreaseRefCounter(&updated) == -1) {
+ if (client->FetchAndIncreaseRefCounter(__func__, &updated) == -1) {
// @client is being deleted. DO NOT touch this @client
ais_rc = SA_AIS_ERR_TRY_AGAIN;
return ais_rc;
@@ -564,7 +578,7 @@ SaAisErrorT LogAgent::saLogFinalize(SaLogHandleT logHandle)
{
// such as Restore the reference counter after fetching & updating.
// or unlock recovery mutex.
ScopeData::LogClientData client_data{client, &updated,
- RefCounterDegree::kDecOne};
+ RefCounter::Degree::kDecOne, __func__};
ScopeData data{&client_data, &is_locked};
if (true) {
@@ -578,7 +592,7 @@ SaAisErrorT LogAgent::saLogFinalize(SaLogHandleT logHandle)
{
return ais_rc;
}
- if (client->FetchAndDecreaseRefCounter(&updated) != 0) {
+ if (client->FetchAndDecreaseRefCounter(__func__, &updated) != 0) {
// DO NOT delete this @client as it is being used by somewhere (>0)
// Or it is being deleted by other thread (=-1)
ais_rc = SA_AIS_ERR_TRY_AGAIN;
@@ -812,7 +826,7 @@ SaAisErrorT LogAgent::saLogStreamOpen_2(
// such as Restore the reference counter after fetching & updating.
// or unlock recovery mutex.
ScopeData::LogClientData client_data{client, &updated,
- RefCounterDegree::kIncOne};
+ RefCounter::Degree::kIncOne, __func__};
ScopeData data{&client_data, &is_locked};
if (lga_is_extended_name_valid(logStreamName) == false) {
@@ -838,7 +852,7 @@ SaAisErrorT LogAgent::saLogStreamOpen_2(
return ais_rc;
}
- if (client->FetchAndIncreaseRefCounter(&updated) == -1) {
+ if (client->FetchAndIncreaseRefCounter(__func__, &updated) == -1) {
// @client is being deleted. DO NOT touch this @client
ais_rc = SA_AIS_ERR_TRY_AGAIN;
return ais_rc;
@@ -1122,9 +1136,9 @@ SaAisErrorT
LogAgent::saLogWriteLogAsync(SaLogStreamHandleT logStreamHandle,
// such as Restore the reference counter after fetching & updating.
// or unlock recovery mutex.
ScopeData::LogClientData client_data{client, &cUpdated,
- RefCounterDegree::kIncOne};
+ RefCounter::Degree::kIncOne, __func__};
ScopeData::LogStreamInfoData stream_data{stream, &sUpdated,
- RefCounterDegree::kIncOne};
+ RefCounter::Degree::kIncOne, __func__};
ScopeData data{&client_data, &stream_data, &is_locked};
if (true) {
@@ -1146,13 +1160,13 @@ SaAisErrorT
LogAgent::saLogWriteLogAsync(SaLogStreamHandleT logStreamHandle,
return ais_rc;
}
- if (client->FetchAndIncreaseRefCounter(&cUpdated) == -1) {
+ if (client->FetchAndIncreaseRefCounter(__func__, &cUpdated) == -1) {
// @client is being deleted. DO NOT touch this @client
ais_rc = SA_AIS_ERR_TRY_AGAIN;
return ais_rc;
}
- if (stream->FetchAndIncreaseRefCounter(&sUpdated) == -1) {
+ if (stream->FetchAndIncreaseRefCounter(__func__, &sUpdated) == -1) {
ais_rc = SA_AIS_ERR_TRY_AGAIN;
return ais_rc;
}
@@ -1292,9 +1306,9 @@ SaAisErrorT LogAgent::saLogStreamClose(SaLogStreamHandleT
logStreamHandle) {
// such as Restore the reference counter after fetching & updating.
// or unlock recovery mutex.
ScopeData::LogClientData client_data{client, &cUpdated,
- RefCounterDegree::kIncOne};
+ RefCounter::Degree::kIncOne, __func__};
ScopeData::LogStreamInfoData stream_data{stream, &sUpdated,
- RefCounterDegree::kDecOne};
+ RefCounter::Degree::kDecOne, __func__};
ScopeData data{&client_data, &stream_data, &is_locked};
if (true) {
@@ -1307,7 +1321,7 @@ SaAisErrorT LogAgent::saLogStreamClose(SaLogStreamHandleT
logStreamHandle) {
return ais_rc;
}
- if (stream->FetchAndDecreaseRefCounter(&sUpdated) != 0) {
+ if (stream->FetchAndDecreaseRefCounter(__func__, &sUpdated) != 0) {
// @stream is being used somewhere (>0), DO NOT delete this @stream.
// or @stream is being deleted on other thread (=-1)
ais_rc = SA_AIS_ERR_TRY_AGAIN;
@@ -1322,7 +1336,7 @@ SaAisErrorT LogAgent::saLogStreamClose(SaLogStreamHandleT
logStreamHandle) {
return ais_rc;
}
- if (client->FetchAndIncreaseRefCounter(&cUpdated) == -1) {
+ if (client->FetchAndIncreaseRefCounter(__func__, &cUpdated) == -1) {
ais_rc = SA_AIS_ERR_TRY_AGAIN;
return ais_rc;
}
diff --git a/src/log/agent/lga_client.cc b/src/log/agent/lga_client.cc
index 2d7c623..386c849 100644
--- a/src/log/agent/lga_client.cc
+++ b/src/log/agent/lga_client.cc
@@ -32,7 +32,7 @@
// LogClient
//------------------------------------------------------------------------------
LogClient::LogClient(const SaLogCallbacksT* cb, uint32_t id, SaVersionT ver)
- : client_id_{id}, ref_counter_{0} {
+ : client_id_{id}, ref_counter_object_{} {
TRACE_ENTER();
// Reset registered callback info
memset(&callbacks_, 0, sizeof(callbacks_));
@@ -65,13 +65,16 @@ LogClient::LogClient(const SaLogCallbacksT* cb, uint32_t
id, SaVersionT ver)
// even they are in the same thread context.
// To avoid such risk, use RECURSIVE MUTEX for @LogClient
pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&mutex_, nullptr);
- pthread_mutexattr_destroy(&attr);
+ int result = pthread_mutexattr_init(&attr);
+ assert(result == 0 && "Failed to init mutex attribute");
+
+ result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ assert(result == 0 && "Failed to set mutex type");
- // Initialize @ref_counter_mutex_
- pthread_mutex_init(&ref_counter_mutex_, nullptr);
+ result = pthread_mutex_init(&mutex_, nullptr);
+ assert(result == 0 && "Failed to init mutex");
+
+ pthread_mutexattr_destroy(&attr);
}
LogClient::~LogClient() {
@@ -94,51 +97,9 @@ LogClient::~LogClient() {
// Free the allocated mailbox for this client
m_NCS_IPC_RELEASE(&mailbox_, nullptr);
- pthread_mutex_destroy(&ref_counter_mutex_);
pthread_mutex_destroy(&mutex_);
}
-// Return (-1) if @this object is being deleted.
-// Otherwise, increase the reference counter.
-int32_t LogClient::FetchAndIncreaseRefCounter(bool* updated) {
- TRACE_ENTER();
- ScopeLock scopeLock(ref_counter_mutex_);
- int32_t backup = ref_counter_;
- *updated = false;
- TRACE("%s: value = %d", __func__, ref_counter_);
- // The @this object is being deleted.
- if (ref_counter_ == -1) return backup;
- ref_counter_ += 1;
- *updated = true;
- return backup;
-}
-
-// Return (0) if @this object is allowed to deleted
-// Otherwise, @this object is being used or being deleted by
-// other thread.
-int32_t LogClient::FetchAndDecreaseRefCounter(bool* updated) {
- TRACE_ENTER();
- ScopeLock scopeLock(ref_counter_mutex_);
- int32_t backup = ref_counter_;
- *updated = false;
- TRACE("%s: value = %d", __func__, ref_counter_);
- // The @this object is being used or being deleted.
- if (ref_counter_ != 0) return backup;
- ref_counter_ = -1;
- *updated = true;
- return backup;
-}
-
-void LogClient::RestoreRefCounter(RefCounterDegree value, bool updated) {
- TRACE_ENTER();
- if (updated == false) return;
- ScopeLock scopeLock(ref_counter_mutex_);
- ref_counter_ -= value;
- TRACE("%s: value = %d", __func__, ref_counter_);
- // Don't expect the @ref_counter_ is less than (-1)
- assert(ref_counter_ >= -1);
-}
-
bool LogClient::ClearMailBox(NCSCONTEXT arg, NCSCONTEXT msg) {
TRACE_ENTER();
lgsv_msg_t *cbk, *pnext;
@@ -413,7 +374,8 @@ bool LogClient::HaveLogStreamInUse() {
TRACE_ENTER();
ScopeLock scopeLock(mutex_);
for (const auto& s : stream_list_) {
- if ((s != nullptr) && (s->ref_counter_ > 0)) return true;
+ if ((s != nullptr) && (s->ref_counter_object_.ref_counter() > 0))
+ return true;
}
return false;
}
diff --git a/src/log/agent/lga_client.h b/src/log/agent/lga_client.h
index eb1efd4..b86869c 100644
--- a/src/log/agent/lga_client.h
+++ b/src/log/agent/lga_client.h
@@ -21,13 +21,14 @@
#include <stdint.h>
#include <vector>
#include <atomic>
+#include <saLog.h>
#include "base/mutex.h"
#include "mds/mds_papi.h"
-#include <saLog.h>
#include "log/agent/lga_stream.h"
#include "log/common/lgsv_msg.h"
#include "log/common/lgsv_defs.h"
#include "log/agent/lga_state.h"
+#include "log/agent/lga_ref_counter.h"
//>
// @LogClient class
@@ -44,7 +45,7 @@
// After adding @this LogClient object to the database of @LogAgent,
// The proper way to retrieve @this object is via SearchClientById()
// or SeachClientByHandle(), and the next call MUST be
-// FetchAndUpdateObjectState() on that object to update its ref counter.
+// FetchAndUpdateRefCounter() on that object to update its ref counter.
//
// This object contains lot of important information about the log client,
// such as the mailbox @mailbox_ for putting all MDS msg which belong to
@@ -57,10 +58,10 @@
// @saLogStreamOpen successfully, and removed from the database
// when @saLogStreamClose is called successfully.
//
-// And each @LogClient object has one special attribute, called @ref_counter_,
-// that attribute should be updated when it is refered, modify or deleting.
-// FetchAndUpdateObjectState()/RestoreObjectState() are methods to
-// increase/restore the @ref_counter_
+// And each @LogClient object owns one special object, ref_counter_object_,
+// that object should be updated when it is referred, modified or deleted.
+// FetchAnd<xxx>RefCounter()/RestoreRefCounter() are methods to update
+// ref_counter_object_ object.
//
// @LogClient object can be deleted ONLY if no log stream which it owns
// are in "being use" state (@ref_counter > 0).
@@ -144,18 +145,23 @@ class LogClient {
bool is_stale_client() const;
// Fetch and increase reference counter.
- // Increase one if @this object is not being deleted by other thread.
- // @updated will be set to true if there is an increase, false otherwise.
- int32_t FetchAndIncreaseRefCounter(bool* updated);
+ // Refer to `RefCounter` class for more info.
+ int32_t FetchAndIncreaseRefCounter(const char* caller, bool* updated) {
+ return ref_counter_object_.FetchAndIncreaseRefCounter(caller, updated);
+ }
// Fetch and decrease reference counter.
- // Decrease one if @this object is not being used or deleted by other thread.
- // @updated will be set to true if there is an decrease, false otherwise.
- int32_t FetchAndDecreaseRefCounter(bool* updated);
+ // Refer to `RefCounter` class for more info.
+ int32_t FetchAndDecreaseRefCounter(const char* caller, bool* updated) {
+ return ref_counter_object_.FetchAndDecreaseRefCounter(caller, updated);
+ }
// Restore the reference counter back.
- // Passing @value is either (1) [increase] or (-1) [decrease]
- void RestoreRefCounter(RefCounterDegree value, bool updated);
+ // Refer to `RefCounter` class for more info.
+ void RestoreRefCounter(const char* caller, RefCounter::Degree value,
+ bool updated) {
+ return ref_counter_object_.RestoreRefCounter(caller, value, updated);
+ }
// true if @this client does NOT recovery succcessfully.
// false, otherwise.
@@ -249,15 +255,8 @@ class LogClient {
pthread_mutex_t mutex_;
// Hold information how many thread are referring to this object
- // If the object is being deleted, the value is (-1).
- // If the object is not being deleted/used, the value is (0)
- // If there are N thread referring to this object, the counter will be N.
- int32_t ref_counter_;
-
- // Dedicate an own mutex to protect @ref_counter_.
- // The reason not sharing the @mutex_ is to avoid deadlock with MDS thread
- // E.g: lock(mutex_) --> send MDS sync --> receiving ack from MDS -->
deadlock
- pthread_mutex_t ref_counter_mutex_;
+ // Refer to `RefCounter` class for more info.
+ RefCounter ref_counter_object_;
// Hold all log streams belong to @this client
std::vector<LogStreamInfo*> stream_list_;
diff --git a/src/log/agent/lga_common.h b/src/log/agent/lga_common.h
index ef63cbb..87bd9e7 100644
--- a/src/log/agent/lga_common.h
+++ b/src/log/agent/lga_common.h
@@ -22,14 +22,6 @@
#include "base/osaf_utility.h"
#include "base/macros.h"
-// Degree of reference counter decrease/increase
-enum RefCounterDegree {
- // Say, I want referring to object. Count me in.
- kIncOne = 1,
- // Say, I want to delete the object.
- kDecOne = -1
-};
-
// LOG server state. The state changes according to getting MDS events.
enum class LogServerState {
// No Active LOG server. Could happen a short time during
failover/switchover.
diff --git a/src/log/agent/lga_mds.cc b/src/log/agent/lga_mds.cc
index 81791c0..ca94957 100644
--- a/src/log/agent/lga_mds.cc
+++ b/src/log/agent/lga_mds.cc
@@ -111,8 +111,7 @@ static uint32_t lga_enc_finalize_msg(NCS_UBAID *uba,
lgsv_msg_t *msg) {
return total_bytes;
}
-static uint32_t encode_sanamet(NCS_UBAID *uba, uint8_t *p8, SaNameT *name)
-{
+static uint32_t encode_sanamet(NCS_UBAID *uba, uint8_t *p8, SaNameT *name) {
uint32_t total_bytes = 0;
p8 = ncs_enc_reserve_space(uba, 2);
if (!p8) {
@@ -527,7 +526,7 @@ static uint32_t lga_lgs_msg_proc(lgsv_msg_t *lgsv_msg,
// @client is being deleted in other thread. DO NOT touch this.
bool updated = false;
- if (client->FetchAndIncreaseRefCounter(&updated) == -1) {
+ if (client->FetchAndIncreaseRefCounter(__func__, &updated) == -1) {
LogAgent::instance().LeaveCriticalSection();
lga_msg_destroy(lgsv_msg);
TRACE_LEAVE();
@@ -619,7 +618,7 @@ static uint32_t lga_lgs_msg_proc(lgsv_msg_t *lgsv_msg,
break;
}
- client->RestoreRefCounter(RefCounterDegree::kIncOne, updated);
+ client->RestoreRefCounter(__func__, RefCounter::Degree::kIncOne, updated);
TRACE_LEAVE();
return rc;
}
diff --git a/src/log/agent/lga_ref_counter.cc b/src/log/agent/lga_ref_counter.cc
new file mode 100644
index 0000000..25574f7
--- /dev/null
+++ b/src/log/agent/lga_ref_counter.cc
@@ -0,0 +1,73 @@
+/* -*- OpenSAF -*-
+ *
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "log/agent/lga_ref_counter.h"
+#include <assert.h>
+#include "base/logtrace.h"
+
+//------------------------------------------------------------------------------
+// RefCounter
+//------------------------------------------------------------------------------
+RefCounter::RefCounter() : ref_counter_{0}, ref_counter_mutex_{} {}
+
+// Return (-1) if @this object is being deleted.
+// Otherwise, increase the reference counter.
+int32_t RefCounter::FetchAndIncreaseRefCounter(const char* caller,
+ bool* updated) {
+ TRACE_ENTER();
+ assert(caller != nullptr && updated != nullptr);
+ base::Lock scopeLock(ref_counter_mutex_);
+ int32_t backup = ref_counter_;
+ *updated = false;
+ TRACE("%s(%s): counter(%d) = %d", __func__, caller, *updated, ref_counter_);
+ // The @this object is being deleted.
+ if (ref_counter_ == -1) return backup;
+ ref_counter_ += 1;
+ *updated = true;
+ return backup;
+}
+
+// Return (0) if @this object is allowed to deleted
+// Otherwise, @this object is being used or being deleted by
+// other thread.
+int32_t RefCounter::FetchAndDecreaseRefCounter(const char* caller,
+ bool* updated) {
+ TRACE_ENTER();
+ assert(caller != nullptr && updated != nullptr);
+ base::Lock scopeLock(ref_counter_mutex_);
+ int32_t backup = ref_counter_;
+ *updated = false;
+ TRACE("%s(%s): counter(%d) = %d", __func__, caller, *updated, ref_counter_);
+ // @this object is being used or being deleted.
+ if (ref_counter_ != 0) return backup;
+ ref_counter_ = -1;
+ *updated = true;
+ return backup;
+}
+
+void RefCounter::RestoreRefCounter(const char* caller,
+ Degree value, bool updated) {
+ TRACE_ENTER();
+ assert(caller != nullptr && "No caller");
+ if (updated == false) return;
+ base::Lock scopeLock(ref_counter_mutex_);
+ int degree = (value == Degree::kIncOne ? 1 : -1);
+ ref_counter_ -= degree;
+ TRACE("%s(%s): counter(%d) = %d", __func__, caller, degree, ref_counter_);
+ // Don't expect the @ref_counter_ is less than (-1)
+ assert(ref_counter_ >= -1);
+}
diff --git a/src/log/agent/lga_ref_counter.h b/src/log/agent/lga_ref_counter.h
new file mode 100644
index 0000000..4fbd28f
--- /dev/null
+++ b/src/log/agent/lga_ref_counter.h
@@ -0,0 +1,117 @@
+/* -*- OpenSAF -*-
+ *
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef SRC_LOG_AGENT_LGA_REF_COUNTER_H_
+#define SRC_LOG_AGENT_LGA_REF_COUNTER_H_
+
+#include <stdint.h>
+#include "log/agent/lga_common.h"
+#include "base/mutex.h"
+
+//>
+// The reference counter class is used to synchronize access
+// to its object owner. The class provides helper methods
+// to let the owner object know how many thread are referring
+// to owner object, is owner object deleting.
+//
+// So, by using this RefCounter object, the owner can avoid data race.
+//
+// When the object owner is refering for reading/modifying, the caller
+// firstly should check if the object is being deleted or not by
+// using method `FetchAndIncreaseRefCounter()`. If there is deletion going,
+// means the return value is (-1), the caller should not touch this object
+// by returning try again, otherwise could get coredump.
+//
+// And if the object owner is going to be deleted, the caller firstly check
+// if if the object is being used by other thread or not by calling method
+// `FetchAndDecreaseRefCounter`. If there is thread referring to this object,
+// the method will return non-zero (!=0). In that case, the caller
+// should not delete the object, otherwise could get coredump.
+//
+// When calling any methods of this class, the first parameter, `caller`,
+// is used mainly for trace purpose. It will be helpful to detect who
+// is the caller to these methods.
+//
+// Usage example:
+// class Owner {
+// public:
+// RefCounter ref_counter_object_;
+//}
+//
+// <! Case #1: Using Owner object !>
+// if (ref_counter_object_.FetchAndIncreaseRefCounter() == -1) {
+// // Return try again and come back later
+// }
+//
+// // It is ok to refer to Owner object.
+//
+//
+// <! Case #2: Delete Owner object !>
+// if (ref_counter_object_.FetchAndDecreaseRefCounter() != 0) {
+// // The owner is using or deleting by other thread. Return try again.
+// }
+//
+// // It is ok to delete the Owner object.
+//<
+class RefCounter {
+ public:
+ // Degree of reference counter. Introduce to force caller either using
+ // kIncOne (1) or kDecOne(-1). Other value is not allowed.
+ enum Degree {
+ // Say, I want referring to object. Count me in.
+ kIncOne = 1,
+ // Say, I want to delete the object.
+ kDecOne = -1
+ };
+
+ RefCounter();
+ ~RefCounter() {};
+
+ // Fetch and increase reference counter.
+ // Increase one if @this object is not being deleted by other thread.
+ // @updated will be set to true if there is an increase, false otherwise.
+ // @caller shows who is the caller, the main purpose is for debugging.
+ int32_t FetchAndIncreaseRefCounter(const char* caller, bool* updated);
+
+ // Fetch and decrease reference counter.
+ // Decrease one if @this object is not being used or deleted by other thread.
+ // @updated will be set to true if there is an decrease, false otherwise.
+ // @caller shows who is the caller, the main purpose is for debugging.
+ int32_t FetchAndDecreaseRefCounter(const char* caller, bool* updated);
+
+ // Restore the reference counter back if @updated is true.
+ // Passed @value is either (1) [increase] or (-1) [decrease]
+ // @caller shows who is the caller, the main purpose is for debugging.
+ void RestoreRefCounter(const char* caller, Degree value, bool updated);
+
+ // Return current ref_counter_ value
+ int32_t ref_counter() const { return ref_counter_; }
+
+ private:
+ // Hold information how many thread are referring to this object
+ // If the object is being deleted, the value is (-1).
+ // If the object is not being deleted/used, the value is (0)
+ // If there are N thread referring to this object, the counter will be N.
+ int32_t ref_counter_;
+
+ // The mutex to protect @ref_counter_.
+ base::Mutex ref_counter_mutex_;
+
+ DELETE_COPY_AND_MOVE_OPERATORS(RefCounter);
+};
+
+#endif // SRC_LOG_AGENT_LGA_REF_COUNTER_H_
diff --git a/src/log/agent/lga_stream.cc b/src/log/agent/lga_stream.cc
index d64ee13..8481f42 100644
--- a/src/log/agent/lga_stream.cc
+++ b/src/log/agent/lga_stream.cc
@@ -28,7 +28,7 @@
#include "mds/mds_papi.h"
LogStreamInfo::LogStreamInfo(const std::string& name, uint32_t id)
- : stream_name_{name}, ref_counter_mutex_{}, ref_counter_{0} {
+ : stream_name_{name} {
TRACE_ENTER();
stream_id_ = id;
recovered_flag_ = true;
@@ -49,50 +49,6 @@ LogStreamInfo::~LogStreamInfo() {
}
}
-// Return (-1) if @this object is being deleted.
-// Otherwise, increase the reference counter.
-int32_t LogStreamInfo::FetchAndIncreaseRefCounter(bool* updated) {
- TRACE_ENTER();
- base::Lock scopeLock(ref_counter_mutex_);
- int32_t backup = ref_counter_;
- *updated = false;
- TRACE("%s: value = %d", __func__, ref_counter_);
- // The @this object is being deleted.
- if (ref_counter_ == -1) return backup;
- ref_counter_ += 1;
- *updated = true;
- return backup;
-}
-
-// Return (0) if @this object is allowed to deleted
-// Otherwise, @this object is being used or being deleted by
-// other thread.
-int32_t LogStreamInfo::FetchAndDecreaseRefCounter(bool* updated) {
- TRACE_ENTER();
- base::Lock scopeLock(ref_counter_mutex_);
- int32_t backup = ref_counter_;
- *updated = false;
- TRACE("%s: value = %d", __func__, ref_counter_);
- // The @this object is being used or being deleted.
- if (ref_counter_ != 0) return backup;
- ref_counter_ = -1;
- *updated = true;
- return backup;
-}
-
-void LogStreamInfo::RestoreRefCounter(RefCounterDegree value, bool updated) {
- TRACE_ENTER();
- if (updated == false) return;
- base::Lock scopeLock(ref_counter_mutex_);
- // @value is negative number in case restoring the counter
- // for @FetchAndDecreaseRefCounter().
- // Should be a positive number, otherwise.
- ref_counter_ -= value;
- TRACE("%s: value = %d", __func__, ref_counter_);
- // Don't expect the @ref_counter_ is less than (-1)
- assert(ref_counter_ >= -1);
-}
-
bool LogStreamInfo::SendOpenStreamMsg(uint32_t client_id) {
TRACE_ENTER();
SaAisErrorT ais_rc = SA_AIS_OK;
diff --git a/src/log/agent/lga_stream.h b/src/log/agent/lga_stream.h
index 5b9f6f9..abacbe3 100644
--- a/src/log/agent/lga_stream.h
+++ b/src/log/agent/lga_stream.h
@@ -23,6 +23,7 @@
#include <saLog.h>
#include "base/mutex.h"
#include "log/agent/lga_common.h"
+#include "log/agent/lga_ref_counter.h"
//<
// @LogStreamInfo class
@@ -53,9 +54,13 @@
// @LogClient.
//
// To avoid @this LogStreamInfo object deleted while it is being used by other
-// thread, such as one client thread is performing writing log record,
-// in the meantime, other client thread is closing that that log stream
-// or closing the owning @LogClient. (! refer to @LogAgent description for
more)
+// thread, such as one client thread is performing writing log record, in the
+// meantime, other client thread is closing that that log stream or closing the
+// owning @LogClient. (! refer to @LogAgent description for more) , one special
+// object `RefCounter` is included in. Each @LogStreamInfo object owns one
+// ref_counter_object_, that object should be updated when this object is
+// using, modified or deleted. FetchAnd<xxx>RefCounter()/RestoreRefCounter()
+// are methods to update ref_counter_object_ object.
//
// When SC restarts from headless, @this object will be notified to do
// recover itself for specific @LogClient Id.
@@ -83,18 +88,20 @@ class LogStreamInfo {
const std::string& GetStreamName() const { return stream_name_; }
// Fetch and increase reference counter.
- // Increase one if @this object is not being deleted by other thread.
- // @updated will be set to true if there is an increase, false otherwise.
- int32_t FetchAndIncreaseRefCounter(bool* updated);
+ int32_t FetchAndIncreaseRefCounter(const char* caller, bool* updated) {
+ return ref_counter_object_.FetchAndIncreaseRefCounter(caller, updated);
+ }
// Fetch and decrease reference counter.
- // Decrease one if @this object is not being used or deleted by other thread.
- // @updated will be set to true if there is an decrease, false otherwise.
- int32_t FetchAndDecreaseRefCounter(bool* updated);
+ int32_t FetchAndDecreaseRefCounter(const char* caller, bool* updated) {
+ return ref_counter_object_.FetchAndDecreaseRefCounter(caller, updated);
+ }
// Restore the reference counter back.
- // Passing @value is either (1) [increase] or (-1) [decrease]
- void RestoreRefCounter(RefCounterDegree value, bool updated);
+ void RestoreRefCounter(const char* caller, RefCounter::Degree value,
+ bool updated) {
+ return ref_counter_object_.RestoreRefCounter(caller, value, updated);
+ }
private:
// Set stream open flags @open_flags_
@@ -119,16 +126,9 @@ class LogStreamInfo {
// Log stream name mentioned during open log stream
std::string stream_name_;
- // To protect @ref_counter_
- // E.g: if @this object is being used in @saLogStreamWrite
- // and other thread trying to delete it, will get TRY_AGAIN.
- base::Mutex ref_counter_mutex_;
-
// Hold information how many thread are referring to this object
- // If the object is being deleted, the value is (-1).
- // If the object is not being deleted/used, the value is (0)
- // If there are N thread referring to this object, the counter will be N.
- int32_t ref_counter_;
+ // Refer to `RefCounter` class for more info.
+ RefCounter ref_counter_object_;
// Log stream open flags as defined in AIS.02.01
SaLogStreamOpenFlagsT open_flags_;
--
1.9.1
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel