ROOTANA
Loading...
Searching...
No Matches
netDirectoryServer.cxx
Go to the documentation of this file.
1/********************************************************************\
2
3 Name: netDirectoryServer.cxx
4 Created by: Konstantin Olchanski & Stefan Ritt
5
6 Contents: Server component for the ROOT TNetDirectory
7
8 $Id$
9
10\********************************************************************/
11
12#include <stdio.h>
13#include <assert.h>
14
15#include "netDirectoryServer.h"
16
17/*==== ROOT socket histo server ====================================*/
18
19#if 1
20#define THREADRETURN
21#define THREADTYPE void
22#endif
23#if defined( OS_WINNT )
24#define THREADRETURN 0
25#define THREADTYPE DWORD WINAPI
26#endif
27#ifndef THREADTYPE
28#define THREADTYPE int
29#define THREADRETURN 0
30#endif
31
32#include <TROOT.h>
33#include <TClass.h>
34#include <TFile.h>
35#include <TDirectory.h>
36#include <TKey.h>
37#include <TFolder.h>
38#include <TSocket.h>
39#include <TServerSocket.h>
40#include <TThread.h>
41#include <TMessage.h>
42#include <TObjString.h>
43#include <TH1.h>
44#include <TCutG.h>
45
46#include <deque>
47#include <map>
48#include <string>
49
50#include "RootLock.h"
51
52static bool gVerbose = false;
53
54static std::deque<std::string> gExports;
55static std::map<std::string,std::string> gExportNames;
56
57/*------------------------------------------------------------------*/
58
59static TObject* FollowPath(TObject* container, char* path)
60{
61 while (1)
62 {
63 if (0)
64 printf("Follow path [%s] in container %p\n", path, container);
65
66 while (*path == '/')
67 path++;
68
69 char* s = strchr(path,'/');
70
71 if (s)
72 *s = 0;
73
74 TObject *obj = NULL;
75
76 if (container->InheritsFrom(TDirectory::Class()))
77 obj = ((TDirectory*)container)->FindObject(path);
78 else if (container->InheritsFrom(TFolder::Class()))
79 obj = ((TFolder*)container)->FindObject(path);
80 else if (container->InheritsFrom(TCollection::Class()))
81 obj = ((TCollection*)container)->FindObject(path);
82 else
83 {
84 printf("ERROR: Container \'%s\' of type %s is not a TDirectory, TFolder or TCollection\n", container->GetName(), container->IsA()->GetName());
85 return NULL;
86 }
87
88 if (!s)
89 return obj;
90
91 if (!obj)
92 return NULL;
93
94 container = obj;
95
96 path = s+1;
97 }
98 /* NOT REACHED */
99}
100
101static TObject* FindTopLevelObject(const char* name)
102{
103 TObject *obj = NULL;
104 //gROOT->GetListOfFiles()->Print();
105 obj = gROOT->GetListOfFiles()->FindObject(name);
106 if (obj)
107 return obj;
108 obj = gROOT->FindObjectAny(name);
109 if (obj)
110 return obj;
111 return NULL;
112}
113
114static TObject* TopLevel(char* path, char**opath)
115{
116 if (0)
117 printf("Extract top level object from [%s]\n", path);
118
119 while (*path == '/')
120 path++;
121
122 char* s = strchr(path,'/');
123
124 if (s)
125 {
126 *s = 0;
127 *opath = s+1;
128 }
129 else
130 {
131 *opath = NULL;
132 }
133
134 TObject *obj = NULL;
135
136 for (unsigned int i=0; i<gExports.size(); i++)
137 {
138 const char* ename = gExports[i].c_str();
139 //printf("Compare [%s] and [%s]\n", path, ename);
140 if (strcmp(path, ename) == 0)
141 {
142 const char* xname = gExportNames[ename].c_str();
143 obj = FindTopLevelObject(xname);
144 //printf("Lookup of [%s] returned %p\n", xname, obj);
145 break;
146 }
147 }
148
149 if (!obj)
150 {
151 printf("ERROR: Top level object \'%s\' not found in exports list\n", path);
152 return NULL;
153 }
154
155 return obj;
156}
157
158static TObject* FollowPath(char* path)
159{
160 if (0)
161 printf("Follow path [%s]\n", path);
162
163 char *s;
164 TObject *obj = TopLevel(path, &s);
165
166 if (!obj)
167 return NULL;
168
169 if (!s)
170 return obj;
171
172 return FollowPath(obj, s);
173}
174
175/*------------------------------------------------------------------*/
176
177static void ResetObject(TObject* obj)
178{
179 assert(obj!=NULL);
180
181 if (gVerbose)
182 printf("ResetObject object %p name [%s] type [%s]\n", obj, obj->GetName(), obj->IsA()->GetName());
183
184 if (obj->InheritsFrom(TH1::Class()))
185 {
186 ((TH1*)obj)->Reset();
187 }
188 else if (obj->InheritsFrom(TDirectory::Class()))
189 {
190 TDirectory* dir = (TDirectory*)obj;
191 TList* objs = dir->GetList();
192
193 TIter next = objs;
194 while(1)
195 {
196 TObject *obj = next();
197 if (obj == NULL)
198 break;
199 ResetObject(obj);
200 }
201 }
202}
203
204/*------------------------------------------------------------------*/
205
206static TKey* MakeKey(TObject* obj, int cycle, TDirectory* dir, const char* name = NULL)
207{
208 static TDirectory* xfile = NULL;
209 if (!xfile)
210 xfile = new TFile("/dev/null");
211
212 TClass *xclass = obj->IsA();
213
214 if (xclass->InheritsFrom(TDirectory::Class()))
215 xclass = TDirectory::Class();
216 else if (xclass->InheritsFrom(TFolder::Class()))
217 xclass = TDirectory::Class();
218 else if (xclass->InheritsFrom(TCollection::Class()))
219 xclass = TDirectory::Class();
220
221 if (!name)
222 name = obj->GetName();
223
224 //return new TKey(name, obj->GetTitle(), xclass, cycle, dir);
225 return new TKey(name, obj->GetTitle(), xclass, 0, xfile);
226}
227
228/*------------------------------------------------------------------*/
229
231/*
232 Serve histograms over TCP/IP socket link
233*/
234{
235 char request[2560];
236
237 TSocket *sock = (TSocket *) arg;
238 TMessage message(kMESS_OBJECT);
239
240 do {
241
242 /* close connection if client has disconnected */
243 int rd = sock->Recv(request, sizeof(request));
244 if (rd <= 0)
245 {
246 if (gVerbose)
247 fprintf(stderr, "TNetDirectory connection from %s closed\n", sock->GetInetAddress().GetHostName());
248 sock->Close();
249 delete sock;
250 return THREADRETURN;
251 }
252
253 if (gVerbose)
254 printf("Request [%s] from %s\n", request, sock->GetInetAddress().GetHostName());
255
256 if (strcmp(request, "GetListOfKeys") == 0)
257 {
258 // enumerate top level exported directories
259
260 LockRootGuard lock;
261
262 //printf("Top level exported directories are:\n");
263 TList* keys = new TList();
264
265 for (unsigned int i=0; i<gExports.size(); i++)
266 {
267 const char* ename = gExports[i].c_str();
268 const char* xname = gExportNames[ename].c_str();
269
270 TObject* obj = FindTopLevelObject(xname);
271
272 if (!obj)
273 {
274 fprintf(stderr, "GetListOfKeys: Exported name \'%s\' cannot be found!\n", xname);
275 continue;
276 }
277
278 TKey* key = MakeKey(obj, 1, gROOT, ename);
279 keys->Add(key);
280 }
281
282 if (gVerbose)
283 {
284 printf("Sending keys %p\n", keys);
285 keys->Print();
286 }
287
288 message.Reset(kMESS_OBJECT);
289 message.WriteObject(keys);
290 delete keys;
291 lock.Unlock();
292 sock->Send(message);
293 }
294 else if (strncmp(request, "GetListOfKeys ", 14) == 0)
295 {
296 LockRootGuard lock;
297
298 char* dirname = request + 14;
299
300 TObject* obj = FollowPath(dirname);
301
302 if (obj && obj->InheritsFrom(TDirectory::Class()))
303 {
304 TDirectory* dir = (TDirectory*)obj;
305
306 //printf("Directory %p\n", dir);
307 //dir->Print();
308
309 TList* xkeys = dir->GetListOfKeys();
310 TList* keys = xkeys;
311 if (!keys)
312 keys = new TList();
313
314 //printf("Directory %p keys:\n", dir);
315 //keys->Print();
316
317 TList* objs = dir->GetList();
318
319 //printf("Directory %p objects:\n", dir);
320 //objs->Print();
321
322 TIter next = objs;
323 while(1)
324 {
325 TObject *obj = next();
326
327 //printf("object %p\n", obj);
328
329 if (obj == NULL)
330 break;
331
332 const char* name = obj->GetName();
333
334 if (!keys->FindObject(name))
335 {
336 TKey* key = MakeKey(obj, 1, dir);
337 keys->Add(key);
338 }
339 }
340
341 //printf("Sending keys %p\n", keys);
342 //keys->Print();
343
344 message.Reset(kMESS_OBJECT);
345 message.WriteObject(keys);
346 if (keys != xkeys)
347 delete keys;
348 }
349 else if (obj && obj->InheritsFrom(TFolder::Class()))
350 {
351 TFolder* folder = (TFolder*)obj;
352
353 //printf("Folder %p\n", folder);
354 //folder->Print();
355
356 TIterator *iterator = folder->GetListOfFolders()->MakeIterator();
357
358 TList* keys = new TList();
359
360 while (1)
361 {
362 TNamed *obj = (TNamed*)iterator->Next();
363 if (obj == NULL)
364 break;
365
366 const char* name = obj->GetName();
367
368 if (!keys->FindObject(name))
369 {
370 TKey* key = MakeKey(obj, 1, gROOT);
371 keys->Add(key);
372 }
373 }
374
375 delete iterator;
376
377 if (gVerbose)
378 {
379 printf("Sending keys %p\n", keys);
380 keys->Print();
381 }
382
383 message.Reset(kMESS_OBJECT);
384 message.WriteObject(keys);
385 delete keys;
386 }
387 else if (obj && obj->InheritsFrom(TCollection::Class()))
388 {
389 TCollection* collection = (TCollection*)obj;
390
391 //printf("Collection %p\n", collection);
392 //collection->Print();
393
394 TIterator *iterator = collection->MakeIterator();
395
396 TList* keys = new TList();
397
398 while (1)
399 {
400 TNamed *obj = (TNamed*)iterator->Next();
401 if (obj == NULL)
402 break;
403
404 const char* name = obj->GetName();
405
406 if (!keys->FindObject(name))
407 {
408 TKey* key = MakeKey(obj, 1, gROOT);
409 keys->Add(key);
410 }
411 }
412
413 delete iterator;
414
415 if (gVerbose)
416 {
417 printf("Sending keys %p\n", keys);
418 keys->Print();
419 }
420
421 message.Reset(kMESS_OBJECT);
422 message.WriteObject(keys);
423 delete keys;
424 }
425 else if (obj)
426 {
427 fprintf(stderr, "netDirectoryServer: ERROR: obj %p name %s, type %s is not a directory!\n", obj, obj->GetName(), obj->IsA()->GetName());
428 TObjString s("Not a directory");
429 message.Reset(kMESS_OBJECT);
430 message.WriteObject(&s);
431 }
432 else
433 {
434 fprintf(stderr, "netDirectoryServer: ERROR: obj %p not found\n", obj);
435 TObjString s("Not found");
436 message.Reset(kMESS_OBJECT);
437 message.WriteObject(&s);
438 }
439
440 lock.Unlock();
441 sock->Send(message);
442 }
443 else if (strncmp(request, "FindObjectByName ", 17) == 0)
444 {
445 LockRootGuard lock;
446
447 char* top = request + 17;
448
449 char *s;
450 TObject *obj = TopLevel(top, &s);
451
452 //printf("toplevel found %p for \'%s\' remaining \'%s\'\n", obj, top, s);
453
454 if (obj && !s)
455 {
456 // they requested a top-level object. Give out a fake name
457
458 char str[256];
459 sprintf(str, "TDirectory %s", obj->GetName());
460
461 for (unsigned int i=0; i<gExports.size(); i++)
462 {
463 const char* ename = gExports[i].c_str();
464 const char* xname = gExportNames[ename].c_str();
465
466 if (strcmp(xname, obj->GetName()) == 0)
467 {
468 sprintf(str, "TDirectory %s", ename);
469 break;
470 }
471 }
472
473 obj = new TObjString(str); // FIXME: memory leak!
474 }
475 else if (obj)
476 {
477 obj = FollowPath(obj, s);
478 }
479
480 if (obj && obj->InheritsFrom(TDirectory::Class()))
481 {
482 char str[256];
483 sprintf(str, "TDirectory %s", obj->GetName());
484 obj = new TObjString(str);
485 }
486
487 if (obj && obj->InheritsFrom(TFolder::Class()))
488 {
489 char str[256];
490 sprintf(str, "TDirectory %s", obj->GetName());
491 obj = new TObjString(str);
492 }
493
494 if (obj && obj->InheritsFrom(TCollection::Class()))
495 {
496 char str[256];
497 sprintf(str, "TDirectory %s", obj->GetName());
498 obj = new TObjString(str);
499 }
500
501 if (gVerbose)
502 {
503 if (obj)
504 printf("Sending object %p name \'%s\' class \'%s\'\n", obj, obj->GetName(), obj->IsA()->GetName());
505 else
506 printf("Sending object %p\n", obj);
507 //obj->Print();
508 }
509
510 message.Reset(kMESS_OBJECT);
511 message.WriteObject(obj);
512 lock.Unlock();
513 sock->Send(message);
514 }
515 else if (strncmp(request, "ResetTH1 ", 9) == 0)
516 {
517 LockRootGuard lock;
518
519 char* path = request + 9;
520
521 if (strlen(path) > 1)
522 {
523 TObject *obj = FollowPath(path);
524
525 if (obj)
526 ResetObject(obj);
527 }
528 else
529 {
530 for (unsigned int i=0; i<gExports.size(); i++)
531 {
532 const char* ename = gExports[i].c_str();
533 const char* xname = gExportNames[ename].c_str();
534
535 TObject* obj = FindTopLevelObject(xname);
536
537 if (!obj)
538 {
539 fprintf(stderr, "ResetTH1: Exported name \'%s\' cannot be found!\n", xname);
540 continue;
541 }
542
543 ResetObject(obj);
544 }
545 }
546
547 TObjString s("Success");
548
549 message.Reset(kMESS_OBJECT);
550 message.WriteObject(&s);
551 lock.Unlock();
552 sock->Send(message);
553 }
554 else
555 {
556 fprintf(stderr, "netDirectoryServer: Received unknown request \"%s\"\n", request);
557 LockRootGuard lock;
558 TObjString s("Unknown request");
559 message.Reset(kMESS_OBJECT);
560 message.WriteObject(&s);
561 lock.Unlock();
562 sock->Send(message);
563 }
564 } while (1);
565
566 return THREADRETURN;
567}
568
569/*------------------------------------------------------------------*/
570
572{
573 // Server loop listening for incoming network connections on specified port.
574 // Starts a searver_thread for each connection.
575
576 int port = *(int *) arg;
577
578 fprintf(stderr, "NetDirectory server listening on port %d...\n", port);
579 TServerSocket *lsock = new TServerSocket(port, kTRUE);
580
581 while (1)
582 {
583 TSocket *sock = lsock->Accept();
584
585 if (sock==NULL)
586 {
587 printf("TNetDirectory server accept() error\n");
588 break;
589 }
590
591 if (gVerbose)
592 fprintf(stderr, "TNetDirectory connection from %s\n", sock->GetInetAddress().GetHostName());
593
594#if 1
595 TThread *thread = new TThread("NetDirectoryServer", root_server_thread, sock);
596 thread->Run();
597#else
598 LPDWORD lpThreadId = 0;
599 CloseHandle(CreateThread(NULL, 1024, &root_server_thread, sock, 0, lpThreadId));
600#endif
601 }
602
603 return THREADRETURN;
604}
605
606/*------------------------------------------------------------------*/
607
609{
610 gVerbose = verbose;
611 //gDebugLockRoot = verbose;
612}
613
614/*------------------------------------------------------------------*/
615
616static bool gAlreadyRunning = false;
617
618void NetDirectoryExport(TDirectory* dir, const char* exportName)
619{
620 if (gVerbose)
621 printf("Export TDirectory %p named [%s] of type [%s] as [%s]\n", dir, dir->GetName(), dir->IsA()->GetName(), exportName);
622
623 bool found = false;
624 for (unsigned int i=0; i<gExports.size(); i++)
625 {
626 const char* ename = gExports[i].c_str();
627 if (strcmp(ename, exportName) == 0)
628 found = true;
629 }
630
631 if (!found)
632 gExports.push_back(exportName);
633 gExportNames[exportName] = dir->GetName();
634}
635
636void NetDirectoryExport(TFolder* folder, const char* exportName)
637{
638 if (gVerbose)
639 printf("Export TFolder %p named [%s] of type [%s] as [%s]\n", folder, folder->GetName(), folder->IsA()->GetName(), exportName);
640
641 bool found = false;
642 for (unsigned int i=0; i<gExports.size(); i++)
643 {
644 const char* ename = gExports[i].c_str();
645 if (strcmp(ename, exportName) == 0)
646 found = true;
647 }
648
649 if (!found)
650 gExports.push_back(exportName);
651 gExportNames[exportName] = folder->GetName();
652}
653
654void NetDirectoryExport(TCollection* collection, const char* exportName)
655{
656 if (gVerbose)
657 printf("Export TCollection %p named [%s] of type [%s] as [%s]\n", collection, collection->GetName(), collection->IsA()->GetName(), exportName);
658
659 bool found = false;
660 for (unsigned int i=0; i<gExports.size(); i++)
661 {
662 const char* ename = gExports[i].c_str();
663 if (strcmp(ename, exportName) == 0)
664 found = true;
665 }
666
667 if (!found)
668 gExports.push_back(exportName);
669 gExportNames[exportName] = collection->GetName();
670}
671
673{
674 if (dir)
675 NetDirectoryExport(dir, dir->GetName());
676
677 if (gAlreadyRunning)
678 return;
679
680 if (port==0)
681 return;
682
683 gAlreadyRunning = true;
684
686
687 static int pport = port;
688#if 1
689 TThread *thread = new TThread("NetDirectoryServer", socket_listener, &pport);
690 thread->Run();
691#else
692 LPDWORD lpThreadId = 0;
693 CloseHandle(CreateThread(NULL, 1024, &root_socket_server, &pport, 0, lpThreadId));
694#endif
695}
696
697// end
void StartLockRootTimer(int period_msec=100)
Definition RootLock.cxx:115
virtual TList * GetList() const
virtual TList * GetListOfKeys() const
void root_socket_server(void *arg)
static TKey * MakeKey(TObject *obj, int cycle, TDirectory *dir, const char *name=NULL)
static std::deque< std::string > gExports
#define THREADRETURN
#define THREADTYPE
static bool gVerbose
static std::map< std::string, std::string > gExportNames
static TObject * FollowPath(TObject *container, char *path)
void NetDirectoryExport(TDirectory *dir, const char *exportName)
static TObject * FindTopLevelObject(const char *name)
static TObject * TopLevel(char *path, char **opath)
static void ResetObject(TObject *obj)
static THREADTYPE socket_listener(void *arg)
void VerboseNetDirectoryServer(bool verbose)
static bool gAlreadyRunning
static THREADTYPE root_server_thread(void *arg)
void StartNetDirectoryServer(int port, TDirectory *dir)
void Unlock()
Definition RootLock.cxx:53