ROOTANA
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 
52 static bool gVerbose = false;
53 
54 static std::deque<std::string> gExports;
55 static std::map<std::string,std::string> gExportNames;
56 
57 /*------------------------------------------------------------------*/
58 
59 static 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 
101 static 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 
114 static 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 
158 static 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 
177 static 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 
206 static 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 
571 static THREADTYPE socket_listener(void *arg)
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 
608 void VerboseNetDirectoryServer(bool verbose)
609 {
610  gVerbose = verbose;
611  //gDebugLockRoot = verbose;
612 }
613 
614 /*------------------------------------------------------------------*/
615 
616 static bool gAlreadyRunning = false;
617 
618 void 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 
636 void 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 
654 void 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 std::deque< std::string > gExports
static TObject * FollowPath(TObject *container, char *path)
#define THREADRETURN
#define THREADTYPE
static bool gVerbose
static std::map< std::string, std::string > gExportNames
static TObject * TopLevel(char *path, char **opath)
void NetDirectoryExport(TDirectory *dir, const char *exportName)
static void ResetObject(TObject *obj)
static THREADTYPE socket_listener(void *arg)
static TKey * MakeKey(TObject *obj, int cycle, TDirectory *dir, const char *name=NULL)
void VerboseNetDirectoryServer(bool verbose)
static TObject * FindTopLevelObject(const char *name)
static bool gAlreadyRunning
static THREADTYPE root_server_thread(void *arg)
void StartNetDirectoryServer(int port, TDirectory *dir)
void Unlock()
Definition: RootLock.cxx:53