forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
AdminTable.cpp
Go to the documentation of this file.
1 
9 #include "AdminTable.h"
10 
11 namespace forest {
12 
13 
15 AdminTable::AdminTable(int maxAdmins) : maxAdm(maxAdmins) {
16  avec = new Admin[maxAdm+1];
17  admins = new UiSetPair(maxAdm);
18  nameMap = new map<string, int>();
19  maxAdx = 0;
20 }
21 
24  delete [] avec; delete admins; delete nameMap;
25  pthread_mutex_destroy(&mapLock);
26 }
27 
30  if (pthread_mutex_init(&mapLock,NULL) != 0) return false;
31  for (int adx = 1; adx <= maxAdm; adx++) {
32  avec[adx].busyBit = false;
33  if (pthread_cond_init(&avec[adx].busyCond,NULL) != 0)
34  return false;
35  }
36  return true;
37 }
38 
68 int AdminTable::getAdmin(const string& aname) {
69  lockMap();
70  map<string, int>::iterator p = nameMap->find(aname);
71  if (p == nameMap->end()) { unlockMap(); return 0; }
72  int adx = p->second;
73  while (avec[adx].busyBit) { // wait until admin's entry is not busy
74  pthread_cond_wait(&avec[adx].busyCond,&mapLock);
75  p = nameMap->find(aname);
76  if (p == nameMap->end()) {
77  pthread_cond_signal(&avec[adx].busyCond);
78  unlockMap(); return 0;
79  }
80  }
81  avec[adx].busyBit = true; // set busyBit to lock admin table entry
82  unlockMap();
83  return adx;
84 }
85 
90 void AdminTable::releaseAdmin(int adx) {
91  lockMap();
92  avec[adx].busyBit = false;
93  pthread_cond_signal(&avec[adx].busyCond);
94  unlockMap();
95 }
96 
102  lockMap();
103  int adx = admins->firstIn();
104  if (adx == 0) { unlockMap(); return 0; }
105  while (avec[adx].busyBit) {
106  pthread_cond_wait(&avec[adx].busyCond,&mapLock);
107  adx = admins->firstIn(); // first admin may have changed
108  if (adx == 0) {
109  pthread_cond_signal(&avec[adx].busyCond);
110  unlockMap(); return 0;
111  }
112  }
113  avec[adx].busyBit = true;
114  unlockMap();
115  return adx;
116 }
117 
125 int AdminTable::nextAdmin(int adx) {
126  lockMap();
127  int nuAdx = admins->nextIn(adx);
128  if (nuAdx == 0) {
129  avec[adx].busyBit = false;
130  pthread_cond_signal(&avec[adx].busyCond);
131  unlockMap();
132  return 0;
133  }
134  while (avec[nuAdx].busyBit) {
135  pthread_cond_wait(&avec[nuAdx].busyCond,&mapLock);
136  nuAdx = admins->nextIn(adx);
137  if (nuAdx == 0) {
138  avec[adx].busyBit = false;
139  pthread_cond_signal(&avec[adx].busyCond);
140  pthread_cond_signal(&avec[nuAdx].busyCond);
141  unlockMap();
142  return 0;
143  }
144  }
145  avec[nuAdx].busyBit = true;
146  avec[adx].busyBit = false;
147  pthread_cond_signal(&avec[adx].busyCond);
148  unlockMap();
149  return nuAdx;
150 }
151 
165 int AdminTable::addAdmin(string& aname, string& pwd, int adx) {
166  lockMap();
167  map<string,int>::iterator p = nameMap->find(aname);
168  if (p != nameMap->end()) { unlockMap(); return 0; }
169  if (adx != 0) {
170  if (admins->isIn(adx)) adx = 0;
171  } else {
172  adx = admins->firstOut();
173  }
174  if (adx == 0) { unlockMap(); return 0;}
175  nameMap->insert(pair<string,int>(aname,adx));
176  admins->swap(adx);
177  avec[adx].busyBit = true;
178  unlockMap();
179 
180  setAdminName(adx,aname); setPassword(adx,pwd);
181  setRealName(adx,"noname"); setEmail(adx,"nomail");
182 
183  maxAdx = max(adx,maxAdx);
184  return adx;
185 }
186 
192 void AdminTable::removeAdmin(int adx) {
193  lockMap();
194  nameMap->erase(avec[adx].aname);
195  admins->swap(adx);
196  avec[adx].busyBit = false;
197  pthread_cond_signal(&avec[adx].busyCond);
198  unlockMap();
199 }
200 
209 bool AdminTable::readEntry(istream& in, int adx) {
210  string aname, pwd, realName, email;
211 
212  if (!in.good()) return false;
213  if (Misc::verify(in,'+')) {
214  if (!Misc::readName(in, aname) || !Misc::verify(in,',') ||
215  !Misc::readWord(in, pwd) || !Misc::verify(in,',') ||
216  !Misc::readString(in, realName) || !Misc::verify(in,',') ||
217  !Misc::readWord(in, email)) {
218  return false;
219  }
220  Misc::cflush(in,'\n');
221  } else if (Misc::verify(in,'-')) {
222  maxAdx = max(adx, maxAdx);
223  Misc::cflush(in,'\n'); return true;
224  } else {
225  Misc::cflush(in,'\n'); return false;
226  }
227 
228  if (addAdmin(aname, pwd, adx) == 0) return false;
229  setRealName(adx,realName); setEmail(adx,email);
230  releaseAdmin(adx);
231  return true;
232 }
233 
245 bool AdminTable::read(istream& in) {
246  int i = 0;
247  while (readEntry(in,i)) i++;
248  cout << "read " << i << " admin records, producing "
249  << admins->getNumIn() << "table entries\n";
250  return true;
251 }
252 
259 string& AdminTable::admin2string(int adx, string& s) const {
260  string s1;
261  s = getAdminName(adx) + ", " + getPassword(adx) + ", ";
262  s += ", \"" + getRealName(adx) + "\", " + getEmail(adx) + "\n";
263  return s;
264 }
265 
266 
272 string& AdminTable::toString(string& s) {
273  string s1; s = "";
274  for (int adx = firstAdmin(); adx != 0; adx = nextAdmin(adx))
275  s += admin2string(adx,s1);
276  return s;
277 }
278 
282 void AdminTable::write(ostream& out) {
283  string s;
284  for (int adx = firstAdmin(); adx != 0; adx = nextAdmin(adx))
285  out << admin2string(adx,s);
286 }
287 
288 } // ends namespace
289