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