Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : * Copyright Contributors to the OpenSDN project 4 : */ 5 : 6 : #include "db/db_entry.h" 7 : 8 : #include <tbb/mutex.h> 9 : 10 : #include "base/time_util.h" 11 : #include "db/db_table_partition.h" 12 : 13 : using namespace std; 14 : 15 9778384 : DBEntryBase::DBEntryBase() 16 9778384 : : tpart_(NULL), flags(0), last_change_at_(UTCTimestampUsec()) { 17 9780725 : onremoveq_ = false; 18 9781443 : } 19 : 20 9772228 : DBEntryBase::~DBEntryBase() { 21 9772228 : } 22 : 23 3755799 : void DBEntryBase::SetState(DBTableBase *tbl_base, ListenerId listener, 24 : DBState *state) { 25 3755799 : DBTablePartBase *tpart = tbl_base->GetTablePartition(this); 26 3755700 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), true); 27 3757687 : pair<StateMap::iterator, bool> res = state_.insert( 28 3757070 : make_pair(listener, state)); 29 3757295 : if (!res.second) { 30 1230928 : res.first->second = state; 31 : } else { 32 2526367 : assert(!IsDeleted()); 33 : // Account for state addition for this listener. 34 2526379 : tbl_base->AddToDBStateCount(listener, 1); 35 : } 36 3757133 : } 37 : 38 12479332 : DBState *DBEntryBase::GetState(DBTableBase *tbl_base, ListenerId listener) const { 39 12479332 : DBTablePartBase *tpart = tbl_base->GetTablePartition(this); 40 12475760 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), false); 41 12487415 : StateMap::const_iterator loc = state_.find(listener); 42 12471032 : if (loc != state_.end()) { 43 8001769 : return loc->second; 44 : } 45 4472858 : return NULL; 46 12474313 : } 47 : 48 759 : const DBState *DBEntryBase::GetState(const DBTableBase *tbl_base, 49 : ListenerId listener) const { 50 759 : DBTableBase *table = const_cast<DBTableBase *>(tbl_base); 51 759 : DBTablePartBase *tpart = table->GetTablePartition(this); 52 759 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), false); 53 759 : StateMap::const_iterator loc = state_.find(listener); 54 759 : if (loc != state_.end()) { 55 732 : return loc->second; 56 : } 57 27 : return NULL; 58 759 : } 59 : 60 : // 61 : // Concurrency: called from arbitrary task. 62 : // 63 : // Evaluate concurrency issues with DBTablePartBase::RunNotify when making 64 : // changes to this method. We expect that either this method or RunNotify 65 : // is responsible for removing the DBEntryBase when they run concurrently, 66 : // assuming the DBEntryBase is eligible for removal. The dbstate_mutex in 67 : // in DBTablePartBase is used for synchronization. 68 : // 69 : // Remove DBState on this DBEntryBase for the given listener and enqueue 70 : // for removal if appropriate. 71 : // Note that the entry cannot be removed from DBTablePartBase here since 72 : // this method may be called from an arbitrary Task. 73 : // 74 2525689 : void DBEntryBase::ClearState(DBTableBase *tbl_base, ListenerId listener) { 75 2525689 : DBTablePartBase *tpart = tbl_base->GetTablePartition(this); 76 2525582 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), true); 77 : 78 2526253 : assert(state_.erase(listener) != 0); 79 : 80 : // Account for state removal for this listener. 81 2525629 : tbl_base->AddToDBStateCount(listener, -1); 82 : 83 2526364 : if (state_.empty() && IsDeleted() && !is_onlist() && !IsOnRemoveQ()) { 84 524815 : tbl_base->EnqueueRemove(this); 85 : } 86 2526321 : } 87 : 88 1071206 : bool DBEntryBase::is_state_empty(DBTablePartBase *tpart) { 89 1071206 : tbb::spin_rw_mutex::scoped_lock lock(tpart->dbstate_mutex(), false); 90 2142376 : return state_.empty(); 91 1071085 : } 92 : 93 524791 : bool DBEntryBase::is_state_empty_unlocked(DBTablePartBase *tpart) { 94 524791 : return state_.empty(); 95 : } 96 : 97 2198135 : void DBEntryBase::set_last_change_at_to_now() { 98 2198135 : last_change_at_ = UTCTimestampUsec(); 99 2198214 : } 100 : 101 0 : void DBEntryBase::set_last_change_at(uint64_t time) { 102 0 : last_change_at_ = time; 103 0 : } 104 : 105 2329974 : void DBEntryBase::set_last_update_at_to_now() { 106 2329974 : last_update_at_ = UTCTimestampUsec(); 107 2330037 : } 108 : 109 152 : void DBEntryBase::set_last_update_at(uint64_t time) { 110 152 : last_update_at_ = time; 111 152 : } 112 1449462 : void DBEntryBase::set_table_partition(DBTablePartBase *tpart) { 113 1449462 : tpart_ = tpart; 114 1449462 : } 115 : 116 3278380 : DBTablePartBase *DBEntryBase::get_table_partition() const { 117 3278380 : return tpart_; 118 : } 119 : 120 9760772 : DBTableBase *DBEntryBase::get_table() const { 121 9760772 : return (tpart_ ? tpart_->parent() : NULL); 122 : } 123 : 124 0 : const std::string DBEntryBase::last_change_at_str() const { 125 0 : return duration_usecs_to_string(UTCTimestampUsec() - last_change_at_); 126 : } 127 : 128 60154 : void DBEntryBase::Notify() { 129 60154 : tpart_->Notify(this); 130 60154 : } 131 : 132 48076 : void DBEntryBase::Delete() { 133 48076 : if (!IsDeleted()) 134 48076 : tpart_->Delete(this); 135 48076 : }