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 using namespace VOS;
00028
00029 #include <stdio.h>
00030 #include <signal.h>
00031
00032 #include <string>
00033 #include <algorithm>
00034
00035
00036
00037
00038
00039 RemoteVobject::RemoteVobject(const string& name, RemoteSite* s)
00040 : VobjectImplementation(name, s, false), resetChildren(false)
00041 {
00042 addUpdateHandler<RemoteVobject>("core:set-child-update", this, &RemoteVobject::addChildUpdateHandler);
00043 addUpdateHandler<RemoteVobject>("core:insert-child-update", this, &RemoteVobject::addChildUpdateHandler);
00044 addUpdateHandler<RemoteVobject>("core:insert-parent-update", this, &RemoteVobject::addParentUpdateHandler);
00045 addUpdateHandler<RemoteVobject>("core:remove-child-update", this, &RemoteVobject::removeChildUpdateHandler);
00046 addUpdateHandler<RemoteVobject>("core:remove-parent-update", this, &RemoteVobject::removeParentUpdateHandler);
00047 addUpdateHandler<RemoteVobject>("core:type-add-update", this, &RemoteVobject::typeUpdateHandler);
00048 addUpdateHandler<RemoteVobject>("core:start-listening-reply", this, &RemoteVobject::addListenerReplyHandler);
00049 }
00050
00051 void RemoteVobject::sendMessage(Message* m)
00052 {
00053 rREF(Site&, site, getSite(), site.sendMessage(m));
00054 }
00055
00056 void RemoteVobject::sendMessage(MessageBlock* mb)
00057 {
00058 rREF(Site&, site, getSite(), site.sendMessage(mb));
00059 }
00060
00061 RemoteVobject::~RemoteVobject()
00062 {
00063 }
00064
00065 LocalSite& RemoteVobject::initFields(Vobject* v, Message* m, const string& method, bool withnonce)
00066 {
00067 m->setType("message");
00068 LocalSite* ls;
00069 vRef<Site> s = v->getSite();
00070 ls = &(dynamic_cast<RemoteSite*>(&s)->getLocalPeer());
00071
00072 m->setFrom(ls->getURL().getString());
00073 m->setTo(v->getURL().getString());
00074 m->setMethod(method);
00075 if(withnonce) m->generateNonce();
00076
00077
00078 return *ls;
00079 }
00080
00081 Vobject& RemoteVobject::findObject(const string& path)
00082 throw (NoSuchSiteError, NoSuchObjectError, URL::BadURLError, AccessControlError, RemoteError)
00083 {
00084 try {
00085
00086 return VobjectImplementation::findObject(path);
00087 } catch(NoSuchObjectError) { }
00088
00089 unsigned int nextpart;
00090 string nextchild;
00091 if(path[0] == '/') {
00092 rREF(Site&, site, getSite(),
00093 Vobject& v = site.findObject(path.substr(1));
00094 site.release();
00095 return v;
00096 );
00097 } else {
00098 nextpart = (unsigned int)path.find("/");
00099 nextchild = path.substr(0, nextpart).c_str();
00100 }
00101
00102 vRef<ParentChildRelation> f = findChild(nextchild);
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 return VobjectImplementation::findObject(path);
00116 }
00117
00118 const deque<Vobject::ParentChildRelation*>& RemoteVobject::getChildren() throw (AccessControlError, RemoteError)
00119 {
00120 if(childListeners.empty()) {
00121 vRef<Message> m = new Message();
00122 vRef<LocalSite> ls = initFields(this, &m, "core:find-child", true);
00123 m->insertField(-1, "path", "#0");
00124 m->insertField(-1, "to", "");
00125 m->insertField(-1, "path", "#-1");
00126
00127 sendMessage(&m);
00128
00129 resetChildren = true;
00130
00131 vRef<Site> site = getSite();
00132 vRef<Message> r = ls->waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site));
00133 }
00134
00135 return children;
00136 }
00137
00138 const set<Vobject::ParentChildRelation*, Vobject::ParentChildRelation::Cmp>& RemoteVobject::getParents()
00139 throw (AccessControlError, RemoteError)
00140 {
00141 if(parentListeners.empty()) {
00142 pREF(Message*, m, new Message(),
00143 rREF(Site&, site, getSite(),
00144 rREF(LocalSite&, ls, initFields(this, m, "core:get-parents", true),
00145 sendMessage(m);
00146 pREF(Message*, r, ls.waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site)), );
00147 );
00148 );
00149 );
00150 }
00151
00152 return parents;
00153 }
00154
00155 void RemoteVobject::addChildUpdateHandler(Message* m)
00156 {
00157 vRef<Site> s = getSite();
00158 try {
00159 if(&s == dynamic_cast<Site*>(this)) {
00160 resetChildren=false;
00161 } else {
00162 if(resetChildren && m->getMethod() == "core:set-child-update") {
00163 if(children.size() > 0) {
00164 for(int i = (int)children.size() - 1; i >= 0; i--) {
00165 VobjectImplementation::removeChild(this, i);
00166 }
00167 }
00168 resetChildren=false;
00169 }
00170 s->lockNotificationFlush();
00171 for(int i=0; i < m->getNumFields(); ++i) {
00172 const Message::Field& pos=m->getField(i);
00173 if(pos.key != "pos") break;
00174 const Message::Field& name=m->getField(++i);
00175 if(name.key != "name") break;
00176 const Message::Field& path=m->getField(++i);
00177 if(path.key != "path") break;
00178 try {
00179 int position=abs(atoi(pos.value.c_str()));
00180 LOG("sendUpdateMessage", 5, "adding child " + name.value
00181 + " at position " + pos.value);
00182 vRef<Vobject> child = Vobject::findObjectFromRoot(path.value);
00183
00184
00185
00186
00187 bool clc=false;
00188
00189 bool clp=false;
00190 bool plp=false;
00191 bool plc=false;
00192 vRef<RemoteSite> cs = dynamic_cast<RemoteSite*>(&(child->getSite()));
00193 if(childListeners.count(&cs)) {
00194 clc=true;
00195 childListeners.erase(&cs);
00196 }
00197 if(parentListeners.count(&cs)) {
00198 plc=true;
00199 parentListeners.erase(&cs);
00200
00201 }
00202 vRef<RemoteSite> ps = dynamic_cast<RemoteSite*>(&(getSite()));
00203 if(childListeners.count(&*(ps))) {
00204 clp=true;
00205 childListeners.erase(&ps);
00206 }
00207 if(parentListeners.count(&ps)) {
00208 plp=true;
00209 parentListeners.erase(&ps);
00210 }
00211
00212 if(m->getMethod() == "core:set-child-update")
00213 VobjectImplementation::setChild(this, position, name.value, &child);
00214 else
00215 VobjectImplementation::insertChild(this, position, name.value, &child);
00216
00217 if(clc) childListeners.insert(&cs);
00218 if(plc) parentListeners.insert(&cs);
00219 if(clp) childListeners.insert(&ps);
00220 if(plp) parentListeners.insert(&ps);
00221 } catch(NoSuchSiteError) {
00222 } catch(NoSuchObjectError) {
00223 } catch(URL::BadURLError) {
00224 } catch(AccessControlError) {
00225 } catch(RemoteError) {
00226 }
00227 }
00228 }
00229 s->unlockNotificationFlush();
00230 } catch(Message::NoSuchFieldError) {
00231 s->unlockNotificationFlush();
00232 LOG("remotevobject", 2, "Message missing a field on insert/set child?");
00233 } catch(runtime_error e) {
00234 s->unlockNotificationFlush();
00235 LOG("remotevobject", 2, "Caught exception processing insert/set child: " << e.what());
00236 } catch(...) {
00237 LOG("remotevobject", 2, "Something very bad just happened in insert/set child!");
00238 s->unlockNotificationFlush();
00239 }
00240 }
00241
00242 void RemoteVobject::addParentUpdateHandler(Message* m)
00243 {
00244 try {
00245 for(int i=0; i < m->getNumFields(); ++i) {
00246 const Message::Field& pos=m->getField(i);
00247 if(pos.key != "pos") break;
00248 const Message::Field& name=m->getField(++i);
00249 if(name.key != "name") break;
00250 const Message::Field& path=m->getField(++i);
00251 if(path.key != "path") break;
00252 try {
00253 int position=atoi(pos.value.c_str());
00254 LOG("sendUpdateMessage", 5, "adding parent " + name.value
00255 + " at position " + pos.value);
00256 pREF(Vobject*, parent, &(Vobject::findObjectFromRoot(path.value)),
00257 if(MetaObject *m=dynamic_cast<MetaObject*>(parent)) parent=m->getTopObject();
00258 RemoteVobject* rvo = dynamic_cast<RemoteVobject*>(parent);
00259 if(rvo && rvo->childListeners.empty()) {
00260 rvo->VobjectImplementation::setChild(this, position, name.value, this);
00261 }
00262 );
00263 } catch(NoSuchObjectError) { }
00264 }
00265 } catch(Message::NoSuchFieldError) { }
00266 }
00267
00268 void RemoteVobject::removeChildUpdateHandler(Message* m)
00269 {
00270 try {
00271 for(int i=0; i < m->getNumFields(); ++i) {
00272 const Message::Field& pos=m->getField(i);
00273 if(pos.key != "pos") break;
00274 const Message::Field& name=m->getField(++i);
00275 if(name.key != "name") break;
00276 const Message::Field& path=m->getField(++i);
00277 if(path.key != "path") break;
00278
00279 try {
00280
00281 unsigned int posi=abs(atoi(pos.value.c_str()));
00282 if(posi < children.size() && children[posi] && children[posi]->contextual_name == name.value
00283 ) {
00284 VobjectImplementation::removeChild(this, posi);
00285 }
00286
00287 } catch(NoSuchObjectError) {
00288 }
00289 }
00290 } catch(Message::NoSuchFieldError) {
00291 }
00292 }
00293
00294 void RemoteVobject::removeParentUpdateHandler(Message* m)
00295 {
00296 try {
00297 for(int i=0; i < m->getNumFields(); ++i) {
00298 const Message::Field& pos=m->getField(i);
00299 if(pos.key != "pos") break;
00300 const Message::Field& name=m->getField(++i);
00301 if(name.key != "name") break;
00302 const Message::Field& path=m->getField(++i);
00303 if(path.key != "path") break;
00304 try {
00305 int position=atoi(pos.value.c_str());
00306 LOG("sendUpdateMessage", 5, "removing parent " + name.value
00307 + " at position " + pos.value);
00308 pREF(Vobject*, parent, &(Vobject::findObjectFromRoot(path.value)),
00309 RemoteVobject* rvo = dynamic_cast<RemoteVobject*>(parent);
00310 if(rvo && rvo->childListeners.empty()) {
00311 parent->removeChild(position);
00312 }
00313 );
00314 } catch(NoSuchObjectError) { }
00315 }
00316 } catch(Message::NoSuchFieldError) { }
00317 }
00318
00319 void RemoteVobject::typeUpdateHandler(Message* m)
00320 {
00321 for(int i=0; i < m->getNumFields(); ++i) {
00322 const Message::Field& t=m->getField(i);
00323 if(t.key == "type") types.insert(t.value);
00324 }
00325 }
00326
00327
00328
00329 void RemoteVobject::sendUpdateMessage(Message* m)
00330 {
00331
00332 LOG("refcount", 5, "before sending to VobjectImp::sendUpdateMessage count on message " << m->getCount());
00333 VobjectImplementation::sendUpdateMessage(m);
00334 LOG("refcount", 5, "after sending to VobjectImp::sendUpdateMessage count on message " << m->getCount());
00335
00336
00337 LOG("refcount", 5, "before doing stuff, count on message " << m->getCount() << " numchildren " << (unsigned int)children.size());
00338
00339 pair<HandlerMap::iterator, HandlerMap::iterator> hndls = updatehandlers.equal_range(m->getMethod());
00340 for(HandlerMap::iterator i = hndls.first; i != hndls.second; i++) {
00341 try {
00342 (*i).second->sendMessage(m);
00343 } catch(NoSuchObjectError) {
00344 } catch(NoSuchSiteError) {
00345 } catch(URL::BadURLError) {
00346 } catch(AccessControlError) {
00347 }
00348 }
00349
00350 LOG("refcount", 5, "after doing stuff, count on message " << m->getCount());
00351
00352
00353
00354 }
00355
00356 void RemoteVobject::addListenerReplyHandler(Message* m)
00357 {
00358 try {
00359 const Message::Field& f = m->getField("listen");
00360 if(f.value == "types") {
00361 VobjectImplementation::addTypeListener(&DoNothingListener::static_);
00362 } else if(f.value == "parents") {
00363 VobjectImplementation::addParentListener(&DoNothingListener::static_);
00364 } else if(f.value == "children") {
00365 VobjectImplementation::addChildListener(&DoNothingListener::static_);
00366 }
00367 } catch(Message::NoSuchFieldError) { }
00368 }
00369
00370 const set<string>& RemoteVobject::getTypes() throw (AccessControlError, RemoteError)
00371 {
00372 try {
00373
00374 if(types.size() == 0) {
00375 pREF(Message*, m, new Message(),
00376 rREF(LocalSite&, ls, initFields(this, m, "core:get-types", true),
00377
00378 sendMessage(m);
00379
00380 rREF(Site&, site, getSite(),
00381 pREF(Message*, r, ls.waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site)), ));
00382
00383 );
00384 );
00385 }
00386 return VobjectImplementation::getTypes();
00387 } catch(AccessControlError) {
00388 throw;
00389 } catch(RemoteError) {
00390 throw;
00391 } catch(exception& e) {
00392 LOG("RemoteVobject", 0, "ERROR (unexpected exception): " << e.what());
00393 throw;
00394 }
00395 }
00396
00397 Vobject::ParentChildRelation& RemoteVobject::findChild(const string& path)
00398 throw (NoSuchObjectError, AccessControlError, RemoteError)
00399 {
00400 try {
00401
00402 return VobjectImplementation::findChild(path);
00403 } catch(NoSuchObjectError) {
00404 if(! childListeners.empty()) throw;
00405 }
00406
00407 pREF(Message*, m, new Message(),
00408 rREF(LocalSite&, ls, initFields(this, m, "core:find-child", true),
00409 m->insertField(-1, "path", path);
00410
00411 sendMessage(m);
00412 rREF(Site&, site, getSite(),
00413 pREF(Message*, r, ls.waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site)), ));
00414 );
00415 );
00416
00417
00418 return VobjectImplementation::findChild(path);
00419 }
00420
00421
00422 void RemoteVobject::setChild(int position, const string& contextual_name, Vobject* child)
00423 throw (AccessControlError, RemoteError)
00424 {
00425 if(!child) {
00426 if(position < 0) position = (int)children.size() + position;
00427 if(position >= (int)children.size()) position = position % (int)children.size();
00428 ParentChildRelation* pcr = children[position];
00429 if(pcr->contextual_name != contextual_name) return;
00430
00431 vRef<Site> thissite = getSite();
00432
00433 vRef<VobjectEvent> event = new VobjectEvent(VobjectEvent::ChildRemove, *this, *this,
00434 position, pcr->contextual_name, *(pcr->child));
00435
00436 for(set<ChildChangeListener*>::iterator i = childListeners.begin();
00437 i != childListeners.end(); i++)
00438 {
00439 try {
00440 (*i)->notifyChildRemoved(*event);
00441 } catch(runtime_error e) {
00442 LOG("remotevobject", 2, "notifyChildRemoved emitted exception: " << e.what());
00443 } catch(...) {
00444 LOG("remotevobject", 2, "notifyChildRemoved emitted unknown exception");
00445 }
00446 }
00447
00448 if(VobjectImplementation* v = dynamic_cast<VobjectImplementation*>(pcr->child)) {
00449 v->parents.erase(pcr);
00450 pcr->release();
00451 }
00452 pcr->child->release();
00453 pcr->child = 0;
00454 return;
00455 }
00456
00457 if((int)children.size() > position
00458 && children[position]
00459 && children[position]->child == child
00460 && children[position]->contextual_name == contextual_name) return;
00461
00462 pREF(Message*, m, new Message(),
00463 rREF(LocalSite&, ls, initFields(this, m, "core:set-child", true),
00464 char pos[16];
00465 snprintf(pos, sizeof(pos), "%i", position);
00466 m->insertField(-1, "pos", string(pos));
00467 m->insertField(-1, "name", contextual_name);
00468 m->insertField(-1, "path", child->getURL().getString());
00469
00470 sendMessage(m);
00471 rREF(Site&, site, getSite(),
00472 pREF(Message*, r, ls.waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site)), ));
00473 );
00474 );
00475 }
00476
00477 void RemoteVobject::insertChild(int position, const string& contextual_name, Vobject* child)
00478 throw (AccessControlError, RemoteError)
00479 {
00480 pREF(Message*, m, new Message(),
00481 rREF(LocalSite&, ls, initFields(this, m, "core:insert-child", true),
00482 char pos[16];
00483 snprintf(pos, sizeof(pos), "%i", position);
00484 m->insertField(-1, "pos", string(pos));
00485 m->insertField(-1, "name", contextual_name);
00486 m->insertField(-1, "path", child->getURL().getString());
00487
00488 sendMessage(m);
00489 rREF(Site&, site, getSite(),
00490 pREF(Message*, r, ls.waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site)), ));
00491 );
00492 );
00493 }
00494
00495 void RemoteVobject::removeChild(int position)
00496 throw (AccessControlError, RemoteError)
00497 {
00498 vRef<Message> m = new Message();
00499 vRef<LocalSite> ls = initFields(this, &m, "core:remove-child", true);
00500 char pos[16];
00501 snprintf(pos, sizeof(pos), "%i", position);
00502 m->insertField(-1, "pos", pos);
00503 m->insertField(-1, "name", children[position]->contextual_name);
00504 m->insertField(-1, "path", children[position]->child->getURL().getString());
00505
00506 sendMessage(&m);
00507
00508 vRef<Site> site = getSite();
00509 try{
00510 vRef<Message> r = ls->waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site));
00511 } catch(exception& e) {
00512 LOG("remotevobject", 2, "RemoteVobject::removeChild: caught exception from waitFor: " << e.what());
00513 }
00514 }
00515
00516 void RemoteVobject::addTypeListener(TypeChangeListener* tl, bool refresh)
00517 {
00518 if(typeListeners.empty() && refresh) {
00519 types.clear();
00520
00521 vRef<Message> m = new Message();
00522 vRef<LocalSite> ls = initFields(this, &m, "core:start-listening", true);
00523 m->insertField(-1, "listen", "types");
00524 sendMessage(&m);
00525 vRef<Site> site = getSite();
00526 vRef<Message> r = ls->waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site));
00527 }
00528 VobjectImplementation::addTypeListener(tl, refresh);
00529 }
00530
00531 void RemoteVobject::addParentListener(ParentChangeListener* pl, bool refresh)
00532 {
00533 if(parentListeners.empty() && refresh) {
00534 vRef<Message> m = new Message();
00535 vRef<LocalSite> ls = initFields(this, &m, "core:start-listening", true);
00536 m->insertField(-1, "listen", "parents");
00537
00538 sendMessage(&m);
00539 vRef<Site> site = getSite();
00540 vRef<Message> r = ls->waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site));
00541 }
00542 VobjectImplementation::addParentListener(pl, refresh);
00543 }
00544
00545 void RemoteVobject::addChildListener(ChildChangeListener* cl, bool refresh)
00546 {
00547 if(childListeners.empty() && refresh) {
00548 vRef<Message> m = new Message();
00549 vRef<LocalSite> ls = initFields(this, &m, "core:start-listening", true);
00550 m->insertField(-1, "listen", "children");
00551
00552 sendMessage(&m);
00553 vRef<Site> site = getSite();
00554 vRef<Message> r = ls->waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site));
00555 }
00556 VobjectImplementation::addChildListener(cl, refresh);
00557 }
00558
00559 void RemoteVobject::removeTypeListener(TypeChangeListener* tl)
00560 {
00561 VobjectImplementation::removeTypeListener(tl);
00562 if(typeListeners.size() == 1 && typeListeners.count(&DoNothingListener::static_) == 1)
00563 typeListeners.erase(&DoNothingListener::static_);
00564
00565 if(typeListeners.empty()) {
00566 pREF(Message*, m, new Message(),
00567 rREF(LocalSite&, ls, initFields(this, m, "core:stop-listening", false), );
00568 m->insertField(-1, "listen", "types");
00569
00570 sendMessage(m);
00571 );
00572 }
00573 }
00574
00575 void RemoteVobject::removeParentListener(ParentChangeListener* pl)
00576 {
00577 VobjectImplementation::removeParentListener(pl);
00578 if(parentListeners.size() == 1 && parentListeners.count(&DoNothingListener::static_) == 1)
00579 parentListeners.erase(&DoNothingListener::static_);
00580
00581 if(parentListeners.empty()) {
00582 pREF(Message*, m, new Message(),
00583 rREF(LocalSite&, ls, initFields(this, m, "core:stop-listening", false), );
00584 m->insertField(-1, "listen", "parents");
00585
00586 sendMessage(m);
00587 );
00588 }
00589 }
00590
00591 void RemoteVobject::removeChildListener(ChildChangeListener* cl)
00592 {
00593 VobjectImplementation::removeChildListener(cl);
00594 if(childListeners.size() == 1 && childListeners.count(&DoNothingListener::static_) == 1)
00595 childListeners.erase(&DoNothingListener::static_);
00596
00597 if(childListeners.empty()) {
00598 pREF(Message*, m, new Message(),
00599 rREF(LocalSite&, ls, initFields(this, m, "core:stop-listening", false), );
00600 m->insertField(-1, "listen", "children");
00601
00602 sendMessage(m);
00603 );
00604 }
00605 }
00606
00607 void RemoteVobject::addType(const string& s)
00608 {
00609 vRef<Message> m = new Message();
00610 vRef<LocalSite> ls = initFields(this, &m, "core:type-add", true);
00611 m->insertField(-1, "type", s);
00612
00613 sendMessage(&m);
00614
00615 vRef<Site> site = getSite();
00616 try{
00617 vRef<Message> r = ls->waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site));
00618 } catch(exception& e) {
00619 LOG("remotevobject", 2, "RemoteVobject::removeChild: caught exception from waitFor: " << e.what());
00620 }
00621 }
00622
00623
00624 void RemoteVobject::acquire()
00625 {
00626 RefCounted::acquire();
00627 LOG("refcount", 5, "acquire called on " << getURL().getString() << " count is now " << getCount());
00628 }
00629
00630 void RemoteVobject::release()
00631 {
00632 LOG("refcount", 5, "release called on " << getURL().getString() << " count is now " << (getCount()-1));
00633 RefCounted::release();
00634 }