00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "remotesite.hh"
00025 #include "message.hh"
00026
00027 #include <stdio.h>
00028 #include <sys/types.h>
00029 #include <fcntl.h>
00030 #include <errno.h>
00031 #include <cstdarg>
00032 #include <deque>
00033 #include <string>
00034 #include <map>
00035
00036 using namespace VOS;
00037
00038 multimap<string, metaobject_extender_t> RemoteSite::remoteObjectExtensionTable;
00039
00040 RemoteSite::RemoteSite()
00041 : VobjectImplementation("", 0, false), RemoteMetaObject("", 0),
00042 RemoteVobject("", 0), MetaObject(0), localpeer(0), disconnected(false)
00043 {
00044 setGreeted(false);
00045 }
00046
00047 RemoteSite::~RemoteSite()
00048 {
00049 LOG("remotesite", 4, "deleting " << getURL().getString());
00050 if(localpeer) localpeer->release();
00051 }
00052
00053 LocalSite& RemoteSite::getLocalPeer() throw (NoLocalPeerError)
00054 {
00055 if(! localpeer) throw NoLocalPeerError("Remote site has no local peer (it has probably disconnected).");
00056 localpeer->acquire();
00057 return *localpeer;
00058 }
00059
00060 void RemoteSite::flushIncomingBuffers()
00061 {
00062 localpeer->flushIncomingBuffers();
00063 }
00064
00065 void RemoteSite::addNotification(NotifyEvent* ev)
00066 {
00067 localpeer->addNotification(ev);
00068 }
00069
00070 void RemoteSite::flushNotifications()
00071 {
00072 localpeer->flushNotifications();
00073 }
00074
00075 void RemoteSite::lockNotificationFlush()
00076 {
00077 localpeer->lockNotificationFlush();
00078 }
00079
00080 void RemoteSite::unlockNotificationFlush()
00081 {
00082 localpeer->unlockNotificationFlush();
00083 }
00084
00085 void RemoteSite::sendUpdateMessage(Message* m)
00086 {
00087 try {
00088 if(m->getMethod() == "core:insert-child-update"
00089 || m->getMethod() == "core:set-child-update") {
00090 try {
00091 for(int i=0; i < m->getNumFields(); ++i) {
00092 const Message::Field& pos = m->getField(i);
00093 if(pos.key != "pos") break;
00094 const Message::Field& name = m->getField(++i);
00095 if(name.key != "name") break;
00096 const Message::Field& path = m->getField(++i);
00097 if(path.key != "path") break;
00098 deque<string> objtypes;
00099 if((i+1) < m->getNumFields()) {
00100 const Message::Field* type = &(m->getField(i+1));
00101 while(type->key == "type") {
00102 objtypes.push_back(type->value);
00103 i++;
00104 if(i+1 < m->getNumFields()) {
00105 type = &(m->getField(i+1));
00106 } else break;
00107 }
00108 }
00109 bool newobject=false;
00110 int position=atoi(pos.value.c_str());
00111 try {
00112 vRef<ParentChildRelation> c = VobjectImplementation::findChild(name.value);
00113 URL u(path.value);
00114 vRef<Site> st = c->child->getSite();
00115 if(!(c->position == position
00116 && st->hasHostAlias(u.getHostAndPort())
00117 && c->child->getURL().getPath() == u.getPath()))
00118 {
00119 newobject = true;
00120 }
00121 } catch(NoSuchObjectError) {
00122 newobject = true;
00123 }
00124 if(newobject) {
00125 vRef<RemoteMetaObject> rmo = new RemoteMetaObject(name.value, this);
00126
00127 setChild(position, name.value, &rmo);
00128 if(objtypes.size()) {
00129 for(deque<string>::iterator j = objtypes.begin(); j != objtypes.end(); j++) {
00130 if((*j).size() > 0) rmo->types.insert(*j);
00131 }
00132 for(deque<string>::iterator j = objtypes.begin(); j != objtypes.end(); j++) {
00133 if((*j).size() > 0) rmo->handleNewType(*j);
00134 }
00135 } else rmo->getTypes();
00136 }
00137 }
00138 } catch(Message::NoSuchFieldError) { }
00139 }
00140 } catch(NoSuchObjectError) {
00141 } catch(NoSuchSiteError) {
00142 } catch(URL::BadURLError) {
00143 }
00144
00145 LOG("refcount", 5, "before sending to RemoteMetaObject::sendUpdateMessage count on message " << m->getCount());
00146 RemoteMetaObject::sendUpdateMessage(m);
00147 LOG("refcount", 5, "after sending to RemoteMetaObject::sendUpdateMessage count on message " << m->getCount());
00148 }
00149
00150
00151
00152
00153 void RemoteSite::setChild(int position, const string& contextual_name, Vobject* child)
00154 throw (AccessControlError, TimeoutError)
00155 {
00156 if(! child) RemoteVobject::setChild(position, contextual_name, child);
00157 else {
00158 rREF(Site&, s, child->getSite(),
00159 if(&s == this) {
00160 VobjectImplementation::setChild(this, position, contextual_name, child);
00161 } else throw AccessControlError("Cannot change the child of a remote site like this");
00162 );
00163 }
00164 }
00165
00166 void RemoteSite::setURL(const URL& u)
00167 {
00168 url = u;
00169 }
00170
00171 void RemoteSite::excise()
00172 {
00173 for(int i = (int)children.size() - 1; i >= 0; i--) {
00174 ParentChildRelation* c = children[i];
00175 if(c) {
00176 c->acquire();
00177 Vobject* ch = c->child;
00178 if(ch) {
00179 ch->acquire();
00180 ch->excise();
00181 ch->release();
00182 }
00183 c->release();
00184 }
00185 }
00186
00187 RemoteMetaObject::excise();
00188
00189 LOG("refcount", 5, "remotesite: done trying to excise, count on this remote site is " << getCount());
00190
00191 disconnected=true;
00192
00193 if(localpeer && !localpeer->checkScheduleHoldsSite(this)) {
00194 Site::removeSite(*this);
00195 }
00196
00197 if(localpeer) {
00198 localpeer->removeRemotePeer(this);
00199 localpeer = 0;
00200 }
00201
00202
00203
00204 }
00205
00206 void RemoteSite::lockChildNotifyOutgoing(Vobject* v)
00207 {
00208 childlockSet.insert(v);
00209 }
00210
00211 void RemoteSite::unlockChildNotifyOutgoing(Vobject* v, const string& nonce)
00212 {
00213 set<Vobject*>::iterator n = childlockSet.find(v);
00214 if(n != childlockSet.end()) {
00215 childlockSet.erase(n);
00216
00217 vRef<Message> m = new Message();
00218 m->setType("update");
00219 m->setFrom(v->getURL().getString());
00220 m->setTo(getURL().getString());
00221 m->setMethod("core:set-child-update");
00222 m->setNonce(nonce);
00223
00224 const ChildList& c = v->getChildren();
00225 for(ChildList::const_iterator i = c.begin(); i != c.end(); i++) {
00226 m->insertField(-1, "pos", (*i)->position);
00227 m->insertField(-1, "name", (*i)->contextual_name);
00228 m->insertField(-1, "path", (*i)->child->getURL().getString());
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 }
00240 sendMessage(&m);
00241 }
00242 }
00243
00244
00245 void RemoteSite::lockParentNotifyOutgoing(Vobject* v)
00246 {
00247 parentlockSet.insert(v);
00248 }
00249
00250 void RemoteSite::unlockParentNotifyOutgoing(Vobject* v, const string& nonce)
00251 {
00252 set<Vobject*>::iterator n = parentlockSet.find(v);
00253 if(n != parentlockSet.end()) {
00254 parentlockSet.erase(n);
00255
00256 vRef<Message> m = new Message();
00257 m->setType("update");
00258 m->setFrom(v->getURL().getString());
00259 m->setTo(getURL().getString());
00260 m->setMethod("core:insert-parent-update");
00261 m->setNonce(nonce);
00262
00263 const ParentSet& c = v->getParents();
00264 for(ParentSet::const_iterator i = c.begin(); i != c.end(); i++) {
00265 m->insertField(-1, "pos", (*i)->position);
00266 m->insertField(-1, "name", (*i)->contextual_name);
00267 m->insertField(-1, "path", (*i)->parent->getURL().getString());
00268 }
00269 sendMessage(&m);
00270 }
00271 }
00272
00273 void RemoteSite::lockTypeNotifyOutgoing(Vobject* v)
00274 {
00275 typelockSet.insert(v);
00276 }
00277
00278 void RemoteSite::unlockTypeNotifyOutgoing(Vobject* v, const string& nonce)
00279 {
00280 set<Vobject*>::iterator n = typelockSet.find(v);
00281 if(n != typelockSet.end()) {
00282 typelockSet.erase(n);
00283
00284 vRef<Message> m = new Message();
00285 m->setType("update");
00286 m->setFrom(v->getURL().getString());
00287 m->setTo(getURL().getString());
00288 m->setMethod("core:type-add-update");
00289 m->setNonce(nonce);
00290
00291 const TypeSet& c = v->getTypes();
00292 for(TypeSet::const_iterator i = c.begin(); i != c.end(); i++) {
00293 m->insertField(-1, "type", *i);
00294 }
00295 sendMessage(&m);
00296 }
00297 }
00298
00299
00300 void RemoteSite::notifyChildInserted(VobjectEvent& e)
00301 {
00302 if(childlockSet.count(e.getParent())) return;
00303
00304 vRef<Message> m = new Message();
00305 m->setType("update");
00306 m->setFrom(e.getParent()->getURL().getString());
00307 m->setTo(getURL().getString());
00308 m->setMethod("core:insert-child-update");
00309
00310 LOG("notifyChildInserted", 5, "*** here we are! ***");
00311
00312 char x[16];
00313 snprintf(x, sizeof(x), "%i", e.getPosition());
00314 m->insertField(-1, "pos", string(x));
00315 m->insertField(-1, "name", e.getContextualName());
00316 m->insertField(-1, "path", e.getChild()->getURL().getString());
00317 if(meta_cast<Site*>(e.getParent())) {
00318 const TypeSet& ts = getTypes();
00319 if(ts.size()) {
00320 for(TypeSet::const_iterator ti = ts.begin(); ti != ts.end(); ti++) {
00321 m->insertField(-1, "type", *ti);
00322 }
00323 } else {
00324 m->insertField(-1, "type", "");
00325 }
00326 }
00327 sendMessage(&m);
00328 }
00329
00330 void RemoteSite::notifyChildReplaced(VobjectEvent& e)
00331 {
00332 if(childlockSet.count(e.getParent())) return;
00333
00334 vRef<Message> m = new Message();
00335 m->setType("update");
00336 m->setFrom(e.getParent()->getURL().getString());
00337 m->setTo(getURL().getString());
00338 m->setMethod("core:set-child-update");
00339
00340 char x[16];
00341 snprintf(x, sizeof(x), "%i", e.getPosition());
00342 m->insertField(-1, "pos", string(x));
00343 m->insertField(-1, "name", e.getContextualName());
00344 m->insertField(-1, "path", e.getChild()->getURL().getString());
00345
00346 sendMessage(&m);
00347 }
00348
00349 void RemoteSite::notifyChildRemoved(VobjectEvent& e)
00350 {
00351 if(childlockSet.count(e.getParent())) return;
00352
00353 vRef<Message> m = new Message();
00354 m->setType("update");
00355 m->setFrom(e.getParent()->getURL().getString());
00356 m->setTo(getURL().getString());
00357 m->setMethod("core:remove-child-update");
00358
00359 char x[16];
00360 snprintf(x, sizeof(x), "%i", e.getPosition());
00361 m->insertField(-1, "pos", x);
00362 m->insertField(-1, "name", e.getContextualName());
00363 m->insertField(-1, "path", e.getChild()->getURL().getString());
00364
00365 sendMessage(&m);
00366 }
00367
00368 void RemoteSite::notifyParentInserted(VobjectEvent& e)
00369 {
00370 if(parentlockSet.count(e.getChild())) return;
00371
00372 vRef<Message> m = new Message();
00373 m->setType("update");
00374 m->setFrom(e.getChild()->getURL().getString());
00375 m->setTo(getURL().getString());
00376 m->setMethod("core:insert-parent-update");
00377
00378 char x[16];
00379 snprintf(x, sizeof(x), "%i", e.getPosition());
00380 m->insertField(-1, "pos", string(x));
00381 m->insertField(-1, "name", e.getContextualName());
00382 m->insertField(-1, "path", e.getParent()->getURL().getString());
00383
00384 sendMessage(&m);
00385 }
00386
00387 void RemoteSite::notifyParentRemoved(VobjectEvent& e)
00388 {
00389 if(parentlockSet.count(e.getChild())) return;
00390
00391 vRef<Message> m = new Message();
00392 m->setType("update");
00393 m->setFrom(e.getChild()->getURL().getString());
00394 m->setTo(getURL().getString());
00395 m->setMethod("core:remove-parent-update");
00396
00397 char x[16];
00398 snprintf(x, sizeof(x), "%i", e.getPosition());
00399 m->insertField(-1, "pos", string(x));
00400 m->insertField(-1, "name", e.getContextualName());
00401 m->insertField(-1, "path", e.getParent()->getURL().getString());
00402
00403 sendMessage(&m);
00404 }
00405
00406 void RemoteSite::notifyTypeInserted(VobjectEvent& e)
00407 {
00408 if(typelockSet.count(e.getAffectedObject())) return;
00409
00410 vRef<Message> m = new Message();
00411 m->setType("update");
00412 m->setFrom(e.getAffectedObject()->getURL().getString());
00413 m->setTo(getURL().getString());
00414 m->setMethod("core:type-add-update");
00415
00416 m->insertField(-1, "type", e.getNewType());
00417
00418 sendMessage(&m);
00419 }
00420
00421 void RemoteSite::notifyTypeRemoved(VobjectEvent& e)
00422 {
00423 vRef<Message> m = new Message();
00424 m->setType("update");
00425 m->setFrom(e.getAffectedObject()->getURL().getString());
00426 m->setTo(getURL().getString());
00427 m->setMethod("core:remove-type-update");
00428
00429 m->insertField(-1, "type", e.getNewType());
00430
00431 sendMessage(&m);
00432 }
00433
00434 void RemoteSite::release()
00435 {
00436
00437
00438
00439
00440
00441
00442
00443 RemoteVobject::release();
00444 }
00445
00446 void RemoteSite::extendMetaObject(RemoteMetaObject* root, const char* p)
00447 {
00448 pair<MI, MI> g = remoteObjectExtensionTable.equal_range(p);
00449 for(MI it = g.first; it != g.second; it++) {
00450 MetaObject* newext = (*it).second(root, p);
00451 }
00452 }
00453
00454 #if 0
00455 void RemoteSite::extendMetaObject(RemoteMetaObject* root, ...)
00456 {
00457 va_list ap;
00458 va_start(ap, root);
00459 extendMetaObjectV(root, ap);
00460 va_end(ap);
00461 }
00462 #endif
00463
00464
00465 MetaObject* RemoteSite::createMetaObject(const char* desiredname, const deque<string>& typelist)
00466 {
00467
00468 string name = desiredname;
00469 MetaObject* ret = 0;
00470 vRef<Message> m = new Message();
00471 vRef<LocalSite> ls = initFields(this, &m, "core:create-object", true);
00472 m->insertField(-1, "name", name);
00473 for(deque<string>::const_iterator i = typelist.begin(); i != typelist.end(); i++) {
00474 m->insertField(-1, "type", *i);
00475 }
00476 sendMessage(&m);
00477 try {
00478 vRef<Message> r = ls->waitFor(m->getNonce(), this);
00479 try {
00480 const Message::Field f = r->getField("error");
00481 throw AccessControlError(f.value);
00482 } catch(Message::NoSuchFieldError) {
00483 try {
00484 const Message::Field f = r->getField("path");
00485 ret = meta_cast<MetaObject*>(&findObjectFromRoot(f.value));
00486 } catch(Message::NoSuchFieldError) {
00487 throw AccessControlError("reply did not contain path field");
00488 } catch(NoSuchSiteError) {
00489 throw RemoteError("reply path field illegal");
00490 } catch(NoSuchObjectError x) {
00491 throw RemoteError(string("could not access newly created object: ") + x.what());
00492 } catch(URL::BadURLError) {
00493 throw RemoteError("reply path field illegal");
00494 } catch(AccessControlError x) {
00495 throw x;
00496 } catch(RemoteError x) {
00497 throw x;
00498 }
00499 }
00500 } catch(exception& e) {
00501 LOG("remotesite", 2, "RemoteVobject::removeChild: caught exception from waitFor: " << e.what());
00502 }
00503 return ret;
00504 }
00505
00506 MetaObject* RemoteSite::createMetaObject(const char* name, const char* first, ...)
00507 {
00508 MetaObject* ret;
00509 va_list ap;
00510 va_start(ap, first);
00511 deque<string> args;
00512 if(first) {
00513 args.push_back(first);
00514 for(;;) {
00515 char* p=va_arg(ap, char*);
00516 if(p == 0) break;
00517 args.push_back(p);
00518 }
00519 }
00520 try {
00521 ret = createMetaObject(name, args);
00522 } catch(...) {
00523 va_end(ap);
00524 throw;
00525 }
00526 va_end(ap);
00527 return ret;
00528 }
00529
00530
00531 #if 0
00532 MetaObject* RemoteSite::createMetaObject(const deque<string>& typelist)
00533 {
00534 return createMetaObject(generateUniqueName(), typelist);
00535 }
00536
00537 MetaObject* RemoteSite::createMetaObject()
00538 {
00539 return createMetaObjectT(0);
00540 }
00541 MetaObject* RemoteSite::createMetaObjectT(const char* first, ...)
00542 {
00543 MetaObject* ret;
00544 va_list ap;
00545 va_start(ap, first);
00546 deque<string> args;
00547 if(first) args.push_back(first);
00548 if(first) {
00549 for(;;) {
00550 char* p=va_arg(ap, char*);
00551 if(p == 0) break;
00552 args.push_back(p);
00553 }
00554 }
00555 try {
00556 ret = createMetaObject(args);
00557 } catch(...) {
00558 va_end(ap);
00559 throw;
00560 }
00561 va_end(ap);
00562 return ret;
00563 }
00564
00565 MetaObject* RemoteSite::createMetaObjectV(va_list ap)
00566 {
00567 deque<string> args;
00568 for(;;) {
00569 char* p=va_arg(ap, char*);
00570 if(p == 0) break;
00571 args.push_back(p);
00572 }
00573 return createMetaObject(args);
00574 }
00575
00576
00577 MetaObject* RemoteSite::createMetaObjectV(const string& name, va_list ap)
00578 {
00579 deque<string> args;
00580 for(;;) {
00581 char* p=va_arg(ap, char*);
00582 if(p == 0) break;
00583 args.push_back(p);
00584 }
00585 return createMetaObject(name, args);
00586 }
00587 #endif
00588
00589 void RemoteSite::addRemoteObjectExtension(const char* type, metaobject_extender_t newmethod)
00590 {
00591 remoteObjectExtensionTable.insert(multimap<string, metaobject_extender_t>::value_type(string(type), newmethod));
00592 }
00593
00594 void RemoteSite::removeRemoteObjectExtension(const char* type, metaobject_extender_t oldmethod)
00595 {
00596 pair<MI, MI> g = remoteObjectExtensionTable.equal_range(type);
00597 for(MI it = g.first; it != g.second; it++) {
00598 if((*it).second == oldmethod) {
00599 remoteObjectExtensionTable.erase(it);
00600 break;
00601 }
00602 }
00603 }
00604
00605
00606 void RemoteSite::printExtensionTable(ostream& stream) {
00607 for(MI i = remoteObjectExtensionTable.begin(); i != remoteObjectExtensionTable.end(); i++) {
00608 stream << i->first << endl;
00609 }
00610 }
00611
00612 void RemoteSite::catchIncomingMessage(const string& nonce)
00613 {
00614 waitingFor[nonce] = pair<bool, Message*>(false, 0);
00615 }
00616
00617 void RemoteSite::clearCaughtMessage(const string& nonce)
00618 {
00619 if(waitingFor.count(nonce)) {
00620 if(waitingFor[nonce].second)
00621 waitingFor[nonce].second->release();
00622 waitingFor.erase(nonce);
00623 }
00624 }
00625
00626 bool RemoteSite::messageInProgress(const string& nonce)
00627 {
00628 if(waitingFor.count(nonce)) return waitingFor[nonce].first;
00629 else return false;
00630 }
00631
00632 bool RemoteSite::messageReady(const string& nonce)
00633 {
00634 if(waitingFor.count(nonce)) return (waitingFor[nonce].second != 0);
00635 else return false;
00636 }
00637
00638 Message* RemoteSite::retrieveCaughtMessage(const string& nonce)
00639 {
00640 if(waitingFor.count(nonce)) {
00641 Message* m = waitingFor[nonce].second;
00642 if(m) m->acquire();
00643 return m;
00644 }
00645 else return 0;
00646 }