Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "agent_cmn.h"
6 : #include "agent_db.h"
7 : #include <cfg/cfg_init.h>
8 :
9 27 : void AgentDBEntry::SetRefState() const {
10 27 : AgentDBTable *table = static_cast<AgentDBTable *>(get_table());
11 : // Force calling SetState on a const object.
12 : // Ideally, SetState should be 'const method' and StateMap mutable
13 27 : AgentDBEntry *entry = (AgentDBEntry *)this;
14 27 : entry->SetState(table, table->GetRefListenerId(), new AgentDBState(this));
15 27 : }
16 :
17 26 : void AgentDBEntry::ClearRefState() const {
18 26 : AgentDBTable *table = static_cast<AgentDBTable *>(get_table());
19 : // Force calling SetState on a const object.
20 : // Ideally, ClearState should be 'const method' and StateMap mutable
21 26 : AgentDBEntry *entry = (AgentDBEntry *)this;
22 26 : table->OnZeroRefcount(entry);
23 26 : delete(entry->GetState(table, table->GetRefListenerId()));
24 26 : entry->ClearState(table, table->GetRefListenerId());
25 26 : }
26 :
27 114 : bool AgentDBEntry::IsActive() const {
28 114 : return !IsDeleted();
29 : }
30 :
31 2 : DBState *AgentDBEntry::GetAgentDBEntryState(int listener_id) {
32 : DBState *state = dynamic_cast<DBState *>
33 2 : (GetState(get_table(), listener_id));
34 2 : return state;
35 : }
36 :
37 0 : const DBState *AgentDBEntry::GetAgentDBEntryState(int listener_id) const {
38 : const DBState *state = dynamic_cast<const DBState *>
39 0 : (GetState(get_table(), listener_id));
40 0 : return state;
41 : }
42 :
43 27 : void AgentDBEntry::AllocateResources(ResourceManager *resource_manager) {
44 27 : }
45 :
46 26 : void AgentDBEntry::FreeResources(ResourceManager *resource_manager) {
47 26 : }
48 :
49 5 : void AgentDBEntry::PostAdd() {
50 5 : }
51 :
52 11 : static bool FlushNotify(DBTablePartBase *partition, DBEntryBase *e) {
53 11 : if (e->IsDeleted()) {
54 2 : return true;
55 : }
56 :
57 9 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
58 9 : req.key = e->GetDBRequestKey();
59 9 : (static_cast<AgentDBTable *>(e->get_table()))->Process(req);
60 9 : return true;
61 9 : }
62 :
63 8 : static void FlushWalkDone(DBTable::DBTableWalkRef walk_ref,
64 : DBTableBase *partition) {
65 8 : AgentDBTable *table = static_cast<AgentDBTable *>(partition);
66 8 : table->ReleaseWalker(walk_ref);
67 8 : table->reset_flush_walk_ref();
68 8 : }
69 :
70 24 : AgentDBTable::AgentDBTable(DB *db, const std::string &name) :
71 24 : DBTable(db, name), ref_listener_id_(-1), agent_(NULL),
72 24 : OperDBTraceBuf(SandeshTraceBufferCreate(("Oper " + name), 5000)),
73 48 : flush_walk_ref_() {
74 24 : ref_listener_id_ = Register(boost::bind(&AgentDBTable::Notify,
75 : this, _1, _2));
76 24 : };
77 :
78 0 : AgentDBTable::AgentDBTable(DB *db, const std::string &name,
79 0 : bool del_on_zero_refcount) :
80 0 : DBTable(db, name), ref_listener_id_(-1) , agent_(NULL),
81 0 : OperDBTraceBuf(SandeshTraceBufferCreate(("Oper " + name), 5000)),
82 0 : flush_walk_ref_() {
83 0 : ref_listener_id_ = Register(boost::bind(&AgentDBTable::Notify,
84 : this, _1, _2));
85 0 : };
86 :
87 24 : AgentDBTable::~AgentDBTable() {
88 24 : assert(HasWalkers() == false);
89 24 : }
90 :
91 0 : void AgentDBTable::NotifyEntry(DBEntryBase *e) {
92 0 : agent_->ConcurrencyCheck();
93 : DBTablePartBase *tpart =
94 0 : static_cast<DBTablePartition *>(GetTablePartition(e));
95 0 : tpart->Notify(e);
96 0 : }
97 :
98 8 : void AgentDBTable::reset_flush_walk_ref() {
99 8 : flush_walk_ref_ = NULL;
100 8 : }
101 :
102 0 : AgentDBEntry *AgentDBTable::FindActiveEntryNoLock(const DBEntry *key) {
103 0 : AgentDBEntry *entry = static_cast<AgentDBEntry *> (FindNoLock(key));
104 0 : if (entry && (entry->IsActive() == false)) {
105 0 : return NULL;
106 : }
107 0 : return entry;
108 : }
109 :
110 47 : AgentDBEntry *AgentDBTable::FindActiveEntry(const DBEntry *key) {
111 47 : AgentDBEntry *entry = static_cast<AgentDBEntry *> (Find(key));
112 47 : if (entry && (entry->IsActive() == false)) {
113 0 : return NULL;
114 : }
115 47 : return entry;
116 : }
117 :
118 0 : AgentDBEntry *AgentDBTable::FindActiveEntryNoLock(const DBRequestKey *key) {
119 0 : AgentDBEntry *entry = static_cast<AgentDBEntry *>(FindNoLock(key));
120 0 : if (entry && (entry->IsActive() == false)) {
121 0 : return NULL;
122 : }
123 0 : return entry;
124 : }
125 :
126 85 : AgentDBEntry *AgentDBTable::FindActiveEntry(const DBRequestKey *key) {
127 85 : AgentDBEntry *entry = static_cast<AgentDBEntry *>(Find(key));
128 85 : if (entry && (entry->IsActive() == false)) {
129 0 : return NULL;
130 : }
131 85 : return entry;
132 : }
133 :
134 0 : AgentDBEntry *AgentDBTable::Find(const DBEntry *key, bool ret_del) {
135 0 : if (ret_del) {
136 0 : return Find(key);
137 : } else {
138 0 : return FindActiveEntry(key);
139 : }
140 : }
141 :
142 96 : AgentDBEntry *AgentDBTable::Find(const DBRequestKey *key, bool ret_del) {
143 96 : if (ret_del) {
144 96 : return Find(key);
145 : } else {
146 0 : return FindActiveEntry(key);
147 : }
148 : }
149 :
150 47 : AgentDBEntry *AgentDBTable::Find(const DBEntry *key) {
151 47 : return static_cast<AgentDBEntry *> (DBTable::Find(key));
152 : }
153 :
154 181 : AgentDBEntry *AgentDBTable::Find(const DBRequestKey *key) {
155 181 : return static_cast<AgentDBEntry *>(DBTable::Find(key));
156 : }
157 :
158 27 : void AgentDBTablePartition::Add(DBEntry *entry) {
159 27 : entry->set_table_partition(static_cast<DBTablePartBase *>(this));
160 27 : Agent *agent = (static_cast<AgentDBTable *>(parent()))->agent();
161 27 : if (agent) {
162 : (static_cast<AgentDBEntry *>(entry))->AllocateResources
163 27 : (agent->resource_manager());
164 : }
165 27 : DBTablePartition::Add(entry);
166 27 : static_cast<AgentDBEntry *>(entry)->PostAdd();
167 27 : }
168 :
169 26 : void AgentDBTablePartition::Remove(DBEntryBase *entry) {
170 26 : AgentDBEntry *agent_dbentry = static_cast<AgentDBEntry *>(entry);
171 26 : if (agent_dbentry->GetRefCount() != 0) {
172 0 : agent_dbentry->ClearOnRemoveQ();
173 0 : return;
174 : }
175 26 : Agent *agent = (static_cast<AgentDBTable *>(parent()))->agent();
176 26 : if (agent) {
177 : (static_cast<AgentDBEntry *>(entry))->FreeResources
178 26 : (agent->resource_manager());
179 : }
180 26 : DBTablePartition::Remove(entry);
181 : }
182 :
183 0 : bool AgentDBTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &id) {
184 0 : id = boost::uuids::nil_uuid();
185 0 : return false;
186 : }
187 :
188 110 : void AgentDBTable::Input(DBTablePartition *partition, DBClient *client,
189 : DBRequest *req) {
190 110 : AgentKey *key = static_cast<AgentKey *>(req->key.get());
191 :
192 110 : if (key->sub_op_ == AgentKey::ADD_DEL_CHANGE) {
193 97 : DBTable::Input(partition, client, req);
194 97 : return;
195 : }
196 :
197 13 : AgentDBEntry *entry = static_cast<AgentDBEntry *>(partition->Find(key));
198 13 : if (entry && (entry->IsActive() == false)) {
199 0 : return;
200 : }
201 :
202 : // Dont create an entry on RESYNC sub_op
203 13 : if (key->sub_op_ == AgentKey::RESYNC) {
204 13 : if (entry == NULL) {
205 12 : return;
206 : }
207 1 : if (Resync(entry, req)) {
208 1 : partition->Change(entry);
209 : }
210 1 : return;
211 : }
212 0 : return;
213 : }
214 :
215 1 : void AgentDBTable::Clear() {
216 1 : Unregister(ref_listener_id_);
217 1 : assert(!HasListeners());
218 : DBTablePartition *partition = static_cast<DBTablePartition *>(
219 1 : GetTablePartition(0));
220 :
221 1 : DBEntryBase *next = NULL;
222 1 : for (DBEntryBase *entry = partition->GetFirst(); entry; entry = next) {
223 0 : next = partition->GetNext(entry);
224 0 : if (entry->IsDeleted()) {
225 0 : continue;
226 : }
227 0 : partition->Delete(entry);
228 : }
229 1 : }
230 :
231 10 : void AgentDBTable::Process(DBRequest &req) {
232 10 : agent_->ConcurrencyCheck();
233 : DBTablePartition *tpart =
234 10 : static_cast<DBTablePartition *>(GetTablePartition(req.key.get()));
235 10 : tpart->Process(NULL, &req);
236 10 : }
237 :
238 8 : void AgentDBTable::Flush() {
239 16 : flush_walk_ref_ = AllocWalker(boost::bind(FlushNotify, _1, _2),
240 8 : boost::bind(FlushWalkDone, _1, _2));
241 8 : WalkAgain(flush_walk_ref_);
242 8 : }
|