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 
13 
15 ComtreeTable::ComtreeTable(int maxCtx1, int maxComtLink1, LinkTable *lt1)
16  : maxCtx(maxCtx1), maxComtLink(maxComtLink1),
17  lt(lt1) {
18  tbl = new TblEntry[maxCtx+1];
19  comtMap = new IdMap(maxCtx);
21  clMap = new IdMap(maxComtLink);
22 };
23 
26  delete [] tbl; delete comtMap; delete [] clTbl; delete clMap;
27 }
28 
38  int ctx = comtMap->addPair(key(comt));
39  if (ctx == 0) return 0;
40 
41  tbl[ctx].comt = comt;
42  tbl[ctx].plnk = 0;
43  tbl[ctx].cFlag = false;
44  tbl[ctx].comtLinks = new set<int>();
45  tbl[ctx].rtrLinks = new set<int>();
46  tbl[ctx].coreLinks = new set<int>();
47 
48  return ctx;
49 }
50 
57 bool ComtreeTable::removeEntry(int ctx) {
58  if (!validComtIndex(ctx)) return true;
59 
60  set<int>& comtLinks = *tbl[ctx].comtLinks;
61  set<int>::iterator p;
62  // copy out the comtree links, then remove them
63  // so long as none has any registered routes
64  int *clnks = new int[comtLinks.size()];
65  int i = 0;
66  for (p = comtLinks.begin(); p != comtLinks.end(); p++) {
67  if (clTbl[*p].rteSet->size() != 0) return false;
68  clnks[i++] = *p;
69  }
70  while(--i >= 0) removeLink(ctx,clnks[i]);
71  delete [] clnks;
72 
73  comtMap->dropPair(key(tbl[ctx].comt));
74  delete tbl[ctx].comtLinks;
75  delete tbl[ctx].rtrLinks;
76  delete tbl[ctx].coreLinks;
77  return true;
78 }
79 
87 bool ComtreeTable::addLink(int ctx, int lnk, bool rflg, bool cflg) {
88  if (!validComtIndex(ctx)) return false;
89 
90  int cLnk = clMap->addPair(key(getComtree(ctx),lnk));
91  if (cLnk == 0) return false;
92 
93  tbl[ctx].comtLinks->insert(cLnk);
94  clTbl[cLnk].ctx = ctx; clTbl[cLnk].lnk = lnk;
95  clTbl[cLnk].dest = 0; clTbl[cLnk].qnum = 0;
96  clTbl[cLnk].rteSet = new set<int>;
97  lt->registerComt(lnk,ctx);
98 
99  if (rflg) tbl[ctx].rtrLinks->insert(cLnk);
100  if (cflg) tbl[ctx].coreLinks->insert(cLnk);
101 
102  return true;
103 }
104 
112 bool ComtreeTable::removeLink(int ctx, int cLnk) {
113  if (!validComtIndex(ctx) || !validComtLink(cLnk))
114  return false;
115 
116  if (clTbl[cLnk].rteSet->size() != 0) return false;
117  tbl[ctx].comtLinks->erase(cLnk);
118  tbl[ctx].rtrLinks->erase(cLnk);
119  tbl[ctx].coreLinks->erase(cLnk);
120  delete clTbl[cLnk].rteSet;
121  lt->deregisterComt(getLink(cLnk),ctx);
122 
123  clMap->dropPair(key(getComtree(ctx),getLink(cLnk)));
124  return true;
125 }
126 
132 bool ComtreeTable::checkEntry(int ctx) const {
133  if (!validComtIndex(ctx)) return false;
134 
135  // every router link must be a comtree link
136  set<int>& rtrLinks = *tbl[ctx].rtrLinks;
137  set<int>& coreLinks = *tbl[ctx].coreLinks;
138  set<int>::iterator p;
139  for (p = rtrLinks.begin(); p != rtrLinks.end(); p++) {
140  if (!isLink(ctx,getLink(*p))) return false;
141  }
142  // and every core link must be a router link
143  for (p = coreLinks.begin(); p != coreLinks.end(); p++) {
144  if (!isRtrLink(ctx,getLink(*p))) return false;
145  }
146 
147  // parent must be a router
148  int plnk = getPlink(ctx);
149  if (plnk != 0 && !isRtrLink(ctx,plnk)) return false;
150 
151  if (inCore(ctx)) {
152  // parent of a core router must be a core router
153  if (plnk != 0 && !isCoreLink(ctx,plnk)) return false;
154  } else {
155  // and a non-core router has at most one core link
156  int n = tbl[ctx].coreLinks->size();
157  if (n > 1) return false;
158  // and if it has a core link, it must be the parent link
159  if (n == 1 && !isCoreLink(ctx,plnk)) return false;
160  }
161  return true;
162 }
163 
172 void ComtreeTable::readLinks(istream& in, set<int>& links) {
173  do {
174  int lnk;
175  if (!Misc::readNum(in,lnk)) return;
176  links.insert(lnk);
177  } while (Misc::verify(in,','));
178 }
179 
187 bool ComtreeTable::readEntry(istream& in) {
188  int ct, cFlg, plnk;
189 
190  Misc::skipBlank(in);
191  if (!Misc::readNum(in, ct) || ct < 1 ||
192  !Misc::readNum(in, cFlg) ||
193  !Misc::readNum(in, plnk))
194  return false;
195 
196  set<int> comtLinks; readLinks(in, comtLinks);
197  set<int> coreLinks; readLinks(in, coreLinks);
198 
199  Misc::cflush(in,'\n');
200 
201  int ctx = addEntry(ct);
202  if (ctx == 0) return false;
203  setCoreFlag(ctx,cFlg);
204 
205  set<int>::iterator p;
206  for (p = comtLinks.begin(); p != comtLinks.end(); p++) {
207  // if the link is in the core, also add it to the router list
208  int lnk = *p;
209  bool rtrFlag = (lt->getPeerType(lnk) == Forest::ROUTER);
210  bool coreFlag = (coreLinks.find(lnk) != coreLinks.end());
211  if (coreFlag && !rtrFlag) return false;
212  if (!addLink(ctx,lnk,rtrFlag,coreFlag)) return false;
213  int cLnk = getComtLink(ct,lnk);
216  }
217  setPlink(ctx,plnk); // must be done after links are defined
218 
219  if (!checkEntry(ctx)) { removeEntry(ctx); return false; }
220 
221  return true;
222 }
223 
235 bool ComtreeTable::read(istream& in) {
236  int num;
237  Misc::skipBlank(in);
238  if (!Misc::readNum(in,num)) return false;
239  Misc::cflush(in,'\n');
240  for (int i = 1; i <= num; i++) {
241  if (!readEntry(in)) {
242  cerr << "ComtreeTable::read: could not read "
243  << i << "-th comtree\n";
244  return false;
245  }
246  }
247  return true;
248 }
249 
255 string& ComtreeTable::entry2string(int ctx,string& s) const {
256  stringstream ss;
257  ss << setw(9) << getComtree(ctx) << " "
258  << setw(6) << inCore(ctx)
259  << setw(8) << getPlink(ctx) << " ";
260 
261  set<int>& comtLinks = *tbl[ctx].comtLinks;
262  set<int>::iterator p = comtLinks.begin();
263  while (p != comtLinks.end()) {
264  ss << getLink(*p++);
265  if (p != comtLinks.end()) ss << ",";
266  }
267 
268  ss << " ";
269  set<int>& coreLinks = *tbl[ctx].coreLinks;
270  p = coreLinks.begin();
271  if (p == coreLinks.end()) ss << "0";
272  while (p != coreLinks.end()) {
273  ss << getLink(*p++);
274  if (p != coreLinks.end()) ss << ",";
275  }
276  ss << endl;
277  s = ss.str();
278  return s;
279 }
280 
285 string& ComtreeTable::toString(string& s) const {
286  stringstream ss;
287  ss << comtMap->size() << endl;
288  ss << "# comtree coreFlag pLink links"
289  << " coreLinks" << endl;
290  for (int ctx = firstComtIndex(); ctx != 0; ctx = nextComtIndex(ctx))
291  ss << entry2string(ctx,s);
292  s = ss.str();
293  return s;
294 }
295 
296 } // ends namespace
297