forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
ComtreeTable.cpp
1 
9 #include "ComtreeTable.h"
10 
11 namespace forest {
12 
17 ComtreeTable::ComtreeTable(int maxLnk1, int maxCtx1)
18  : maxLnk(maxLnk1), maxCtx(maxCtx1) {
19  comtMap = new HashMap<comt_t,Entry,Hash::u32>(maxCtx,false);
20  comtList = new Dlist[maxLnk];
21  for (int i = 1; i <= maxLnk; i++) comtList[i].resize(maxCtx);
22 }
23 
26  delete comtMap; delete [] comtList;
27 }
28 
37 bool ComtreeTable::addLink(int ctx, int lnk, bool rflg, bool cflg) {
38  if (!validCtx(ctx)) return false;
39  Entry& e = getEntry(ctx);
40  ClnkInfo cli;
41  int cLnk = e.clMap->put(lnk,cli);
42  if (cLnk == 0) return false;
43 
44  if (rflg) e.rtrLinks->addLast(cLnk);
45  if (cflg) e.coreLinks->addLast(cLnk);
46  comtList[lnk].addLast(ctx);
47 
48  return true;
49 }
50 
56 bool ComtreeTable::removeLink(int ctx, int cLnk) {
57  if (!validCtx(ctx)) return false;
58  Entry& e = getEntry(ctx);
59  if (!e.clMap->valid(cLnk)) return false;
60 
61  int lnk = e.clMap->getKey(cLnk);
62  if (lnk == e.pLnk) {
63  return removeEntry(ctx);
64  }
65  e.clMap->remove(lnk);
66  e.rtrLinks->remove(cLnk);
67  e.coreLinks->remove(cLnk);
68  comtList[lnk].remove(ctx);
69  return true;
70 }
71 
81  Entry e;
82  int ctx = comtMap->put(comt,e);
83  return ctx;
84 }
85 
94  if (!validCtx(ctx)) return true;
95  Entry& e = getEntry(ctx);
96 
97  // first remove ctx from comtList[lnk] for all links in comtree
98  for (int clx = e.clMap->first(); clx != 0; clx = e.clMap->next(clx)) {
99  int lnk = e.clMap->getKey(clx);
100  comtList[lnk].remove(ctx);
101  }
102 
103  // now clear the map and lists, then drop comt from comtree mapping
104  e.clMap->clear(); e.rtrLinks->clear(); e.coreLinks->clear();
105 
106  int comt = comtMap->getKey(ctx);
107  comtMap->remove(comt);
108  return true;
109 }
110 
115 void ComtreeTable::purgeLink(int lnk) {
116  int ctx = comtList[lnk].first();
117  while (ctx != 0 ) {
118  Entry& e = getEntry(ctx);
119  if (lnk == e.pLnk) { // skip for now
120  ctx = comtList[lnk].next(ctx);
121  } else {
122  int cLnk = e.clMap->find(lnk);
123  e.clMap->remove(lnk);
124  e.rtrLinks->remove(cLnk);
125  e.coreLinks->remove(cLnk);
126  // now, carefully remove ctx from comtList[lnk]
127  int x = ctx;
128  ctx = comtList[lnk].next(ctx);
129  comtList[lnk].remove(x);
130  }
131  }
132  // now remove comtrees for which lnk==pLnk
133  // note that removeEntry updates comtList[lnk]
134  while (!comtList[lnk].empty()) {
135  removeEntry(comtList[lnk].first());
136  }
137 }
138 
144 bool ComtreeTable::checkEntry(int ctx) const {
145  if (!validCtx(ctx)) return false;
146  Entry& e = getEntry(ctx);
147 
148  for (int cLnk = firstRtrLink(ctx); cLnk != 0;
149  cLnk = nextRtrLink(ctx,cLnk)) {
150  if (!e.clMap->valid(cLnk)) return false;
151  }
152 
153  for (int cLnk = firstCoreLink(ctx); cLnk != 0;
154  cLnk = nextCoreLink(ctx,cLnk)) {
155  if (!e.rtrLinks->member(cLnk)) return false;
156  }
157 
158  // parent must be a router
159  int plnk = getPlink(ctx);
160  if (plnk != 0 && !isRtrLink(ctx,plnk)) return false;
161 
162  if (inCore(ctx)) {
163  // parent of a core router must be a core router
164  if (plnk != 0 && !isCoreLink(ctx,plnk)) return false;
165  } else {
166  // and a non-core router has at most one core link
167  int n = e.coreLinks->length();
168  if (n > 1) return false;
169  // and if it has a core link, it must be the parent link
170  if (n == 1 && !isCoreLink(ctx,plnk)) return false;
171  }
172  return true;
173 }
174 
182 bool ComtreeTable::readEntry(istream& in) {
183  int comt, plnk;
184  Entry e;
185 
186  Util::skipBlank(in);
187  if (!Util::readInt(in, comt) || comt < 1) return false;
188  if (Util::verify(in,'*')) e.coreFlag = true;
189  if (!Util::readInt(in,plnk)) return false;
190 
191  if (!Util::verify(in,'{')) return false;
192  ClnkInfo cli;
195  while (true) {
196  if (Util::verify(in,'}')) break;
197  int lnk;
198  if (!Util::readInt(in,lnk)) return false;
199  int cLnk = e.clMap->put(lnk,cli);
200  if (Util::verify(in,'+')) {
201  e.rtrLinks->addLast(cLnk);
202  } else if (Util::verify(in,'*')) {
203  e.rtrLinks->addLast(cLnk);
204  e.coreLinks->addLast(cLnk);
205  }
206  }
207  Util::nextLine(in);
208 
209  int ctx = comtMap->put(comt,e);
210  if (ctx == 0) return false;
211 
212  setPlink(ctx,plnk); // must be done after links are defined
213 
214  if (!checkEntry(ctx)) { removeEntry(ctx); return false; }
215 
216  return true;
217 }
218 
230 bool ComtreeTable::read(istream& in) {
231  int num;
232  Util::skipBlank(in);
233  if (!Util::readInt(in,num)) return false;
234  Util::nextLine(in);
235  for (int i = 1; i <= num; i++) {
236  if (!readEntry(in)) {
237  cerr << "ComtreeTable::read: could not read "
238  << i << "-th comtree\n";
239  return false;
240  }
241  }
242  return true;
243 }
244 
249 string ComtreeTable::entry2string(int ctx) const {
250  stringstream ss;
251  if (!validCtx(ctx)) return "";
252  Entry& e = getEntry(ctx);
253  int comt = comtMap->getKey(ctx);
254 
255  ss << comt << e.toString() << endl;
256  return ss.str();
257 }
258 
262 string ComtreeTable::toString() const {
263  stringstream ss;
264  ss << comtMap->size() << endl;
265  ss << "# comtree coreFlag pLink links" << endl;
266  for (int ctx = firstComt(); ctx != 0; ctx = nextComt(ctx))
267  ss << entry2string(ctx);
268  return ss.str();
269 }
270 
271 } // ends namespace
272