Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "db/db_entry.h" 6 : 7 : #include <tbb/mutex.h> 8 : 9 : #include "base/time_util.h" 10 : #include "db/db_table_partition.h" 11 : 12 : using namespace std; 13 : 14 9583776 : DBEntryBase::DBEntryBase() 15 9583776 : : tpart_(NULL), flags(0), last_change_at_(UTCTimestampUsec()) { 16 9585409 : onremoveq_ = false; 17 9585169 : } 18 : 19 9570928 : DBEntryBase::~DBEntryBase() { 20 9570928 : } 21 : 22 3715370 : void DBEntryBase::SetState(DBTableBase *tbl_base, ListenerId listener, 23 : DBState *state) { 24 3715370 : DBTablePartBase *tpart = tbl_base->GetTablePartition(this); 25 3715345 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), true); 26 3716952 : pair<StateMap::iterator, bool> res = state_.insert( 27 3716533 : make_pair(listener, state)); 28 3716602 : if (!res.second) { 29 1222816 : res.first->second = state; 30 : } else { 31 2493786 : assert(!IsDeleted()); 32 : // Account for state addition for this listener. 33 2493805 : tbl_base->AddToDBStateCount(listener, 1); 34 : } 35 3716467 : } 36 : 37 12236693 : DBState *DBEntryBase::GetState(DBTableBase *tbl_base, ListenerId listener) const { 38 12236693 : DBTablePartBase *tpart = tbl_base->GetTablePartition(this); 39 12233409 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), false); 40 12244084 : StateMap::const_iterator loc = state_.find(listener); 41 12229364 : if (loc != state_.end()) { 42 7829901 : return loc->second; 43 : } 44 4402985 : return NULL; 45 12232499 : } 46 : 47 763 : const DBState *DBEntryBase::GetState(const DBTableBase *tbl_base, 48 : ListenerId listener) const { 49 763 : DBTableBase *table = const_cast<DBTableBase *>(tbl_base); 50 763 : DBTablePartBase *tpart = table->GetTablePartition(this); 51 763 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), false); 52 763 : StateMap::const_iterator loc = state_.find(listener); 53 763 : if (loc != state_.end()) { 54 730 : return loc->second; 55 : } 56 33 : return NULL; 57 763 : } 58 : 59 : // 60 : // Concurrency: called from arbitrary task. 61 : // 62 : // Evaluate concurrency issues with DBTablePartBase::RunNotify when making 63 : // changes to this method. We expect that either this method or RunNotify 64 : // is responsible for removing the DBEntryBase when they run concurrently, 65 : // assuming the DBEntryBase is eligible for removal. The dbstate_mutex in 66 : // in DBTablePartBase is used for synchronization. 67 : // 68 : // Remove DBState on this DBEntryBase for the given listener and enqueue 69 : // for removal if appropriate. 70 : // Note that the entry cannot be removed from DBTablePartBase here since 71 : // this method may be called from an arbitrary Task. 72 : // 73 2493192 : void DBEntryBase::ClearState(DBTableBase *tbl_base, ListenerId listener) { 74 2493192 : DBTablePartBase *tpart = tbl_base->GetTablePartition(this); 75 2493088 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), true); 76 : 77 2493713 : assert(state_.erase(listener) != 0); 78 : 79 : // Account for state removal for this listener. 80 2493153 : tbl_base->AddToDBStateCount(listener, -1); 81 : 82 2493649 : if (state_.empty() && IsDeleted() && !is_onlist() && !IsOnRemoveQ()) { 83 514229 : tbl_base->EnqueueRemove(this); 84 : } 85 2493702 : } 86 : 87 1060326 : bool DBEntryBase::is_state_empty(DBTablePartBase *tpart) { 88 1060326 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), false); 89 2120637 : return state_.empty(); 90 1060216 : } 91 : 92 514186 : bool DBEntryBase::is_state_empty_unlocked(DBTablePartBase *tpart) { 93 514186 : return state_.empty(); 94 : } 95 : 96 2189946 : void DBEntryBase::set_last_change_at_to_now() { 97 2189946 : last_change_at_ = UTCTimestampUsec(); 98 2190031 : } 99 : 100 0 : void DBEntryBase::set_last_change_at(uint64_t time) { 101 0 : last_change_at_ = time; 102 0 : } 103 : 104 2312695 : void DBEntryBase::set_last_update_at_to_now() { 105 2312695 : last_update_at_ = UTCTimestampUsec(); 106 2312741 : } 107 : 108 150 : void DBEntryBase::set_last_update_at(uint64_t time) { 109 150 : last_update_at_ = time; 110 150 : } 111 1434465 : void DBEntryBase::set_table_partition(DBTablePartBase *tpart) { 112 1434465 : tpart_ = tpart; 113 1434465 : } 114 : 115 3239872 : DBTablePartBase *DBEntryBase::get_table_partition() const { 116 3239872 : return tpart_; 117 : } 118 : 119 9472951 : DBTableBase *DBEntryBase::get_table() const { 120 9472951 : return (tpart_ ? tpart_->parent() : NULL); 121 : } 122 : 123 0 : const std::string DBEntryBase::last_change_at_str() const { 124 0 : return duration_usecs_to_string(UTCTimestampUsec() - last_change_at_); 125 : } 126 : 127 60111 : void DBEntryBase::Notify() { 128 60111 : tpart_->Notify(this); 129 60111 : } 130 : 131 48072 : void DBEntryBase::Delete() { 132 48072 : if (!IsDeleted()) 133 48072 : tpart_->Delete(this); 134 48072 : }