00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <stdio.h>
00013 #include <assert.h>
00014
00015 #include "netDirectoryServer.h"
00016
00017
00018
00019 #if 1
00020 #define THREADRETURN
00021 #define THREADTYPE void
00022 #endif
00023 #if defined( OS_WINNT )
00024 #define THREADRETURN 0
00025 #define THREADTYPE DWORD WINAPI
00026 #endif
00027 #ifndef THREADTYPE
00028 #define THREADTYPE int
00029 #define THREADRETURN 0
00030 #endif
00031
00032 #include <TROOT.h>
00033 #include <TClass.h>
00034 #include <TFile.h>
00035 #include <TDirectory.h>
00036 #include <TKey.h>
00037 #include <TFolder.h>
00038 #include <TSocket.h>
00039 #include <TServerSocket.h>
00040 #include <TThread.h>
00041 #include <TMessage.h>
00042 #include <TObjString.h>
00043 #include <TH1.h>
00044 #include <TCutG.h>
00045
00046 #include <deque>
00047 #include <map>
00048 #include <string>
00049
00050 #include "RootLock.h"
00051
00052 static bool gVerbose = false;
00053
00054 static std::deque<std::string> gExports;
00055 static std::map<std::string,std::string> gExportNames;
00056
00057
00058
00059 static TObject* FollowPath(TObject* container, char* path)
00060 {
00061 while (1)
00062 {
00063 if (0)
00064 printf("Follow path [%s] in container %p\n", path, container);
00065
00066 while (*path == '/')
00067 path++;
00068
00069 char* s = strchr(path,'/');
00070
00071 if (s)
00072 *s = 0;
00073
00074 TObject *obj = NULL;
00075
00076 if (container->InheritsFrom(TDirectory::Class()))
00077 obj = ((TDirectory*)container)->FindObject(path);
00078 else if (container->InheritsFrom(TFolder::Class()))
00079 obj = ((TFolder*)container)->FindObject(path);
00080 else if (container->InheritsFrom(TCollection::Class()))
00081 obj = ((TCollection*)container)->FindObject(path);
00082 else
00083 {
00084 printf("ERROR: Container \'%s\' of type %s is not a TDirectory, TFolder or TCollection\n", container->GetName(), container->IsA()->GetName());
00085 return NULL;
00086 }
00087
00088 if (!s)
00089 return obj;
00090
00091 if (!obj)
00092 return NULL;
00093
00094 container = obj;
00095
00096 path = s+1;
00097 }
00098
00099 }
00100
00101 static TObject* FindTopLevelObject(const char* name)
00102 {
00103 TObject *obj = NULL;
00104
00105 obj = gROOT->GetListOfFiles()->FindObject(name);
00106 if (obj)
00107 return obj;
00108 obj = gROOT->FindObjectAny(name);
00109 if (obj)
00110 return obj;
00111 return NULL;
00112 }
00113
00114 static TObject* TopLevel(char* path, char**opath)
00115 {
00116 if (0)
00117 printf("Extract top level object from [%s]\n", path);
00118
00119 while (*path == '/')
00120 path++;
00121
00122 char* s = strchr(path,'/');
00123
00124 if (s)
00125 {
00126 *s = 0;
00127 *opath = s+1;
00128 }
00129 else
00130 {
00131 *opath = NULL;
00132 }
00133
00134 TObject *obj = NULL;
00135
00136 for (unsigned int i=0; i<gExports.size(); i++)
00137 {
00138 const char* ename = gExports[i].c_str();
00139
00140 if (strcmp(path, ename) == 0)
00141 {
00142 const char* xname = gExportNames[ename].c_str();
00143 obj = FindTopLevelObject(xname);
00144
00145 break;
00146 }
00147 }
00148
00149 if (!obj)
00150 {
00151 printf("ERROR: Top level object \'%s\' not found in exports list\n", path);
00152 return NULL;
00153 }
00154
00155 return obj;
00156 }
00157
00158 static TObject* FollowPath(char* path)
00159 {
00160 if (0)
00161 printf("Follow path [%s]\n", path);
00162
00163 char *s;
00164 TObject *obj = TopLevel(path, &s);
00165
00166 if (!obj)
00167 return NULL;
00168
00169 if (!s)
00170 return obj;
00171
00172 return FollowPath(obj, s);
00173 }
00174
00175
00176
00177 static void ResetObject(TObject* obj)
00178 {
00179 assert(obj!=NULL);
00180
00181 if (gVerbose)
00182 printf("ResetObject object %p name [%s] type [%s]\n", obj, obj->GetName(), obj->IsA()->GetName());
00183
00184 if (obj->InheritsFrom(TH1::Class()))
00185 {
00186 ((TH1*)obj)->Reset();
00187 }
00188 else if (obj->InheritsFrom(TDirectory::Class()))
00189 {
00190 TDirectory* dir = (TDirectory*)obj;
00191 TList* objs = dir->GetList();
00192
00193 TIter next = objs;
00194 while(1)
00195 {
00196 TObject *obj = next();
00197 if (obj == NULL)
00198 break;
00199 ResetObject(obj);
00200 }
00201 }
00202 }
00203
00204
00205
00206 static TKey* MakeKey(TObject* obj, int cycle, TDirectory* dir, const char* name = NULL)
00207 {
00208 static TDirectory* xfile = NULL;
00209 if (!xfile)
00210 xfile = new TFile("/dev/null");
00211
00212 TClass *xclass = obj->IsA();
00213
00214 if (xclass->InheritsFrom(TDirectory::Class()))
00215 xclass = TDirectory::Class();
00216 else if (xclass->InheritsFrom(TFolder::Class()))
00217 xclass = TDirectory::Class();
00218 else if (xclass->InheritsFrom(TCollection::Class()))
00219 xclass = TDirectory::Class();
00220
00221 if (!name)
00222 name = obj->GetName();
00223
00224
00225 return new TKey(name, obj->GetTitle(), xclass, 0, xfile);
00226 }
00227
00228
00229
00230 static THREADTYPE root_server_thread(void *arg)
00231
00232
00233
00234 {
00235 char request[2560];
00236
00237 TSocket *sock = (TSocket *) arg;
00238 TMessage message(kMESS_OBJECT);
00239
00240 do {
00241
00242
00243 int rd = sock->Recv(request, sizeof(request));
00244 if (rd <= 0)
00245 {
00246 if (gVerbose)
00247 fprintf(stderr, "TNetDirectory connection from %s closed\n", sock->GetInetAddress().GetHostName());
00248 sock->Close();
00249 delete sock;
00250 return THREADRETURN;
00251 }
00252
00253 if (gVerbose)
00254 printf("Request [%s] from %s\n", request, sock->GetInetAddress().GetHostName());
00255
00256 if (strcmp(request, "GetListOfKeys") == 0)
00257 {
00258
00259
00260 LockRootGuard lock;
00261
00262
00263 TList* keys = new TList();
00264
00265 for (unsigned int i=0; i<gExports.size(); i++)
00266 {
00267 const char* ename = gExports[i].c_str();
00268 const char* xname = gExportNames[ename].c_str();
00269
00270 TObject* obj = FindTopLevelObject(xname);
00271
00272 if (!obj)
00273 {
00274 fprintf(stderr, "GetListOfKeys: Exported name \'%s\' cannot be found!\n", xname);
00275 continue;
00276 }
00277
00278 TKey* key = MakeKey(obj, 1, gROOT, ename);
00279 keys->Add(key);
00280 }
00281
00282 if (gVerbose)
00283 {
00284 printf("Sending keys %p\n", keys);
00285 keys->Print();
00286 }
00287
00288 message.Reset(kMESS_OBJECT);
00289 message.WriteObject(keys);
00290 delete keys;
00291 lock.Unlock();
00292 sock->Send(message);
00293 }
00294 else if (strncmp(request, "GetListOfKeys ", 14) == 0)
00295 {
00296 LockRootGuard lock;
00297
00298 char* dirname = request + 14;
00299
00300 TObject* obj = FollowPath(dirname);
00301
00302 if (obj && obj->InheritsFrom(TDirectory::Class()))
00303 {
00304 TDirectory* dir = (TDirectory*)obj;
00305
00306
00307
00308
00309 TList* xkeys = dir->GetListOfKeys();
00310 TList* keys = xkeys;
00311 if (!keys)
00312 keys = new TList();
00313
00314
00315
00316
00317 TList* objs = dir->GetList();
00318
00319
00320
00321
00322 TIter next = objs;
00323 while(1)
00324 {
00325 TObject *obj = next();
00326
00327
00328
00329 if (obj == NULL)
00330 break;
00331
00332 const char* name = obj->GetName();
00333
00334 if (!keys->FindObject(name))
00335 {
00336 TKey* key = MakeKey(obj, 1, dir);
00337 keys->Add(key);
00338 }
00339 }
00340
00341
00342
00343
00344 message.Reset(kMESS_OBJECT);
00345 message.WriteObject(keys);
00346 if (keys != xkeys)
00347 delete keys;
00348 }
00349 else if (obj && obj->InheritsFrom(TFolder::Class()))
00350 {
00351 TFolder* folder = (TFolder*)obj;
00352
00353
00354
00355
00356 TIterator *iterator = folder->GetListOfFolders()->MakeIterator();
00357
00358 TList* keys = new TList();
00359
00360 while (1)
00361 {
00362 TNamed *obj = (TNamed*)iterator->Next();
00363 if (obj == NULL)
00364 break;
00365
00366 const char* name = obj->GetName();
00367
00368 if (!keys->FindObject(name))
00369 {
00370 TKey* key = MakeKey(obj, 1, gROOT);
00371 keys->Add(key);
00372 }
00373 }
00374
00375 delete iterator;
00376
00377 if (gVerbose)
00378 {
00379 printf("Sending keys %p\n", keys);
00380 keys->Print();
00381 }
00382
00383 message.Reset(kMESS_OBJECT);
00384 message.WriteObject(keys);
00385 delete keys;
00386 }
00387 else if (obj && obj->InheritsFrom(TCollection::Class()))
00388 {
00389 TCollection* collection = (TCollection*)obj;
00390
00391
00392
00393
00394 TIterator *iterator = collection->MakeIterator();
00395
00396 TList* keys = new TList();
00397
00398 while (1)
00399 {
00400 TNamed *obj = (TNamed*)iterator->Next();
00401 if (obj == NULL)
00402 break;
00403
00404 const char* name = obj->GetName();
00405
00406 if (!keys->FindObject(name))
00407 {
00408 TKey* key = MakeKey(obj, 1, gROOT);
00409 keys->Add(key);
00410 }
00411 }
00412
00413 delete iterator;
00414
00415 if (gVerbose)
00416 {
00417 printf("Sending keys %p\n", keys);
00418 keys->Print();
00419 }
00420
00421 message.Reset(kMESS_OBJECT);
00422 message.WriteObject(keys);
00423 delete keys;
00424 }
00425 else if (obj)
00426 {
00427 fprintf(stderr, "netDirectoryServer: ERROR: obj %p name %s, type %s is not a directory!\n", obj, obj->GetName(), obj->IsA()->GetName());
00428 TObjString s("Not a directory");
00429 message.Reset(kMESS_OBJECT);
00430 message.WriteObject(&s);
00431 }
00432 else
00433 {
00434 fprintf(stderr, "netDirectoryServer: ERROR: obj %p not found\n", obj);
00435 TObjString s("Not found");
00436 message.Reset(kMESS_OBJECT);
00437 message.WriteObject(&s);
00438 }
00439
00440 lock.Unlock();
00441 sock->Send(message);
00442 }
00443 else if (strncmp(request, "FindObjectByName ", 17) == 0)
00444 {
00445 LockRootGuard lock;
00446
00447 char* top = request + 17;
00448
00449 char *s;
00450 TObject *obj = TopLevel(top, &s);
00451
00452
00453
00454 if (obj && !s)
00455 {
00456
00457
00458 char str[256];
00459 sprintf(str, "TDirectory %s", obj->GetName());
00460
00461 for (unsigned int i=0; i<gExports.size(); i++)
00462 {
00463 const char* ename = gExports[i].c_str();
00464 const char* xname = gExportNames[ename].c_str();
00465
00466 if (strcmp(xname, obj->GetName()) == 0)
00467 {
00468 sprintf(str, "TDirectory %s", ename);
00469 break;
00470 }
00471 }
00472
00473 obj = new TObjString(str);
00474 }
00475 else if (obj)
00476 {
00477 obj = FollowPath(obj, s);
00478 }
00479
00480 if (obj && obj->InheritsFrom(TDirectory::Class()))
00481 {
00482 char str[256];
00483 sprintf(str, "TDirectory %s", obj->GetName());
00484 obj = new TObjString(str);
00485 }
00486
00487 if (obj && obj->InheritsFrom(TFolder::Class()))
00488 {
00489 char str[256];
00490 sprintf(str, "TDirectory %s", obj->GetName());
00491 obj = new TObjString(str);
00492 }
00493
00494 if (obj && obj->InheritsFrom(TCollection::Class()))
00495 {
00496 char str[256];
00497 sprintf(str, "TDirectory %s", obj->GetName());
00498 obj = new TObjString(str);
00499 }
00500
00501 if (gVerbose)
00502 {
00503 if (obj)
00504 printf("Sending object %p name \'%s\' class \'%s\'\n", obj, obj->GetName(), obj->IsA()->GetName());
00505 else
00506 printf("Sending object %p\n", obj);
00507
00508 }
00509
00510 message.Reset(kMESS_OBJECT);
00511 message.WriteObject(obj);
00512 lock.Unlock();
00513 sock->Send(message);
00514 }
00515 else if (strncmp(request, "ResetTH1 ", 9) == 0)
00516 {
00517 LockRootGuard lock;
00518
00519 char* path = request + 9;
00520
00521 if (strlen(path) > 1)
00522 {
00523 TObject *obj = FollowPath(path);
00524
00525 if (obj)
00526 ResetObject(obj);
00527 }
00528 else
00529 {
00530 for (unsigned int i=0; i<gExports.size(); i++)
00531 {
00532 const char* ename = gExports[i].c_str();
00533 const char* xname = gExportNames[ename].c_str();
00534
00535 TObject* obj = FindTopLevelObject(xname);
00536
00537 if (!obj)
00538 {
00539 fprintf(stderr, "ResetTH1: Exported name \'%s\' cannot be found!\n", xname);
00540 continue;
00541 }
00542
00543 ResetObject(obj);
00544 }
00545 }
00546
00547 TObjString s("Success");
00548
00549 message.Reset(kMESS_OBJECT);
00550 message.WriteObject(&s);
00551 lock.Unlock();
00552 sock->Send(message);
00553 }
00554 else
00555 {
00556 fprintf(stderr, "netDirectoryServer: Received unknown request \"%s\"\n", request);
00557 LockRootGuard lock;
00558 TObjString s("Unknown request");
00559 message.Reset(kMESS_OBJECT);
00560 message.WriteObject(&s);
00561 lock.Unlock();
00562 sock->Send(message);
00563 }
00564 } while (1);
00565
00566 return THREADRETURN;
00567 }
00568
00569
00570
00571 static THREADTYPE socket_listener(void *arg)
00572 {
00573
00574
00575
00576 int port = *(int *) arg;
00577
00578 fprintf(stderr, "NetDirectory server listening on port %d...\n", port);
00579 TServerSocket *lsock = new TServerSocket(port, kTRUE);
00580
00581 while (1)
00582 {
00583 TSocket *sock = lsock->Accept();
00584
00585 if (sock==NULL)
00586 {
00587 printf("TNetDirectory server accept() error\n");
00588 break;
00589 }
00590
00591 if (gVerbose)
00592 fprintf(stderr, "TNetDirectory connection from %s\n", sock->GetInetAddress().GetHostName());
00593
00594 #if 1
00595 TThread *thread = new TThread("NetDirectoryServer", root_server_thread, sock);
00596 thread->Run();
00597 #else
00598 LPDWORD lpThreadId = 0;
00599 CloseHandle(CreateThread(NULL, 1024, &root_server_thread, sock, 0, lpThreadId));
00600 #endif
00601 }
00602
00603 return THREADRETURN;
00604 }
00605
00606
00607
00608 void VerboseNetDirectoryServer(bool verbose)
00609 {
00610 gVerbose = verbose;
00611
00612 }
00613
00614
00615
00616 static bool gAlreadyRunning = false;
00617
00618 void NetDirectoryExport(TDirectory* dir, const char* exportName)
00619 {
00620 if (gVerbose)
00621 printf("Export TDirectory %p named [%s] of type [%s] as [%s]\n", dir, dir->GetName(), dir->IsA()->GetName(), exportName);
00622
00623 bool found = false;
00624 for (unsigned int i=0; i<gExports.size(); i++)
00625 {
00626 const char* ename = gExports[i].c_str();
00627 if (strcmp(ename, exportName) == 0)
00628 found = true;
00629 }
00630
00631 if (!found)
00632 gExports.push_back(exportName);
00633 gExportNames[exportName] = dir->GetName();
00634 }
00635
00636 void NetDirectoryExport(TFolder* folder, const char* exportName)
00637 {
00638 if (gVerbose)
00639 printf("Export TFolder %p named [%s] of type [%s] as [%s]\n", folder, folder->GetName(), folder->IsA()->GetName(), exportName);
00640
00641 bool found = false;
00642 for (unsigned int i=0; i<gExports.size(); i++)
00643 {
00644 const char* ename = gExports[i].c_str();
00645 if (strcmp(ename, exportName) == 0)
00646 found = true;
00647 }
00648
00649 if (!found)
00650 gExports.push_back(exportName);
00651 gExportNames[exportName] = folder->GetName();
00652 }
00653
00654 void NetDirectoryExport(TCollection* collection, const char* exportName)
00655 {
00656 if (gVerbose)
00657 printf("Export TCollection %p named [%s] of type [%s] as [%s]\n", collection, collection->GetName(), collection->IsA()->GetName(), exportName);
00658
00659 bool found = false;
00660 for (unsigned int i=0; i<gExports.size(); i++)
00661 {
00662 const char* ename = gExports[i].c_str();
00663 if (strcmp(ename, exportName) == 0)
00664 found = true;
00665 }
00666
00667 if (!found)
00668 gExports.push_back(exportName);
00669 gExportNames[exportName] = collection->GetName();
00670 }
00671
00672 void StartNetDirectoryServer(int port, TDirectory* dir)
00673 {
00674 if (dir)
00675 NetDirectoryExport(dir, dir->GetName());
00676
00677 if (gAlreadyRunning)
00678 return;
00679
00680 if (port==0)
00681 return;
00682
00683 gAlreadyRunning = true;
00684
00685 StartLockRootTimer();
00686
00687 static int pport = port;
00688 #if 1
00689 TThread *thread = new TThread("NetDirectoryServer", socket_listener, &pport);
00690 thread->Run();
00691 #else
00692 LPDWORD lpThreadId = 0;
00693 CloseHandle(CreateThread(NULL, 1024, &root_socket_server, &pport, 0, lpThreadId));
00694 #endif
00695 }
00696
00697