Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
httptextlog.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_http
3/// This macro demonstrates custom access and custom drawing for TMsgList class
4/// Main motivation for this example - demonstrate how traffic between server and
5/// client can be minimized and how one could build custom UI in the browser
6///
7/// TMsgList in this tutorial keep last N messages, numbering each with unique identifier
8/// There is TMsgList::Select() method which selects messages from the list
9/// If one specifies identifier, only messages newer than this identifier are selected
10/// In the selection list (TList object of TObjString) first item always identifier for
11/// the latest message in the list
12///
13/// In JavaScript code (httptextlog.js) one uses Select() method to receive latest
14/// messages, which not yet been seen in the browser and display them as text
15/// At maximum, 1000 elements are preserved in the browser.
16///
17/// After macro started, one could open in browser address
18/// ~~~
19/// http://localhost:8080?item=log
20/// ~~~
21/// One could either click item again or enable monitoring to always receive latest messages
22/// Or one could open only this output and nothing else:
23/// ~~~
24/// http://localhost:8080/log/draw.htm?monitoring=2000
25/// ~~~
26/// In last case it could be used in iframe, also it requires less code to load on the page
27///
28/// \macro_code
29///
30/// \author Sergey Linev
31
32
33#include <cstdio>
34#include <cstring>
35
36#include "TNamed.h"
37#include "TList.h"
38#include "TObjString.h"
39#include "TH1.h"
40#include "TH2.h"
41#include "TRandom3.h"
42#include "TSystem.h"
43#include "THttpServer.h"
44#include "TRootSniffer.h"
45#include "TDatime.h"
46#include "TClass.h"
47
48Bool_t bRun = kTRUE;
49
50class TMsgList : public TNamed {
51
52 protected:
53
54 TList fMsgs; // list messages, stored as TObjString
55 Int_t fLimit = 1000; // max number of stored messages
56 Long64_t fCounter = 0; // current message id
57 TList fSelect; //! temporary list used for selection
58 TObjString fStrCounter; //! current id stored in the string
59
60 public:
61
62 TMsgList(const char* name = "log", Int_t limit = 1000) :
63 TNamed(name, "list of log messages"),
64 fLimit(limit)
65 {
66 fMsgs.SetOwner(kTRUE);
67
68 // counter initialized from current time
69 // if application restarted, id will be bigger and request from browser
70 // will not lead to messages lost. Of course, if more than 1000 messages
71 // per second are generated, one could have mismatch
72
73 fCounter = ((Long64_t) TDatime().Get()) * 1000;
74 }
75
76 ~TMsgList() override { fMsgs.Clear(); }
77
78 void AddMsg(const char* msg)
79 {
80 // add message to the list
81 // if number of stored messages bigger than configured, old messages will be removed
82 // zero (msg==0) messages will not be add to the list
83
84 while (fMsgs.GetSize() >= fLimit) {
85 TObject* last = fMsgs.Last();
86 fMsgs.RemoveLast();
87 delete last;
88 }
89 if (!msg) return;
90
91 fMsgs.AddFirst(new TObjString(msg));
92 fCounter++;
93 }
94
95 TList *Select(Int_t max = 0, Long64_t id = 0)
96 {
97 // Central method to select new messages
98 // Current id stored as first item and used on the client to request new portion
99 // One could limit number of returned messages
100
101 Long64_t curr = fCounter;
102 fSelect.Clear();
103
104 if (max == 0) max = fMsgs.GetLast()+1;
105
106 // add current id as first string in the list
107 fStrCounter.SetString(TString::LLtoa(fCounter, 10));
108 fSelect.Add(&fStrCounter);
109
110 TIter iter(&fMsgs);
111 TObject *obj = nullptr;
112 while ((obj = iter()) && (--curr >= id) && (--max >= 0))
113 fSelect.Add(obj);
114
115 return &fSelect;
116 }
117
118 ClassDefOverride(TMsgList, 1); // Custom messages list
119};
120
121void httptextlog()
122{
123 // create logging instance
124 TMsgList *log = new TMsgList("log", 200);
125
126 // create histograms, just for fun
127 TH1D *hpx = new TH1D("hpx","This is the px distribution",100,-4,4);
128 hpx->SetFillColor(48);
129 hpx->SetDirectory(nullptr);
130 TH2F *hpxpy = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4);
131 hpxpy->SetDirectory(nullptr);
132
133 // start http server
134 auto serv = new THttpServer("http:8080");
135
136 // One could specify location of newer version of JSROOT
137 // serv->SetJSROOT("https://root.cern/js/latest/");
138 // serv->SetJSROOT("https://jsroot.gsi.de/dev/");
139
140 // Detect macro file location to specify full path to the JavaScript file
141 TString jspath = "currentdir/", jsname = "httptextlog.mjs";
142 if (gSystem->AccessPathName(jsname)) {
143 // not find javascript in current directory
144 std::string fdir = __FILE__;
145 auto pos = fdir.find("httptextlog.C");
146 if (pos > 0) {
147 // configure special path in server to load JavaScript file
148 fdir.resize(pos);
149 jspath = "customdir/";
150 serv->AddLocation(jspath, fdir.c_str());
151 } else {
152 printf("Cannot detect directory with macro - not possible to load JavaScript file\n");
153 return;
154 }
155 }
156
157 // let always load httptextlog.mjs script in the browser
158 serv->GetSniffer()->SetAutoLoad("/" + jspath + jsname);
159
160 // register histograms
161 serv->Register("/", hpx);
162 serv->Register("/", hpxpy);
163
164 // register log instance
165 serv->Register("/", log);
166
167 // while server runs in read-only mode, we should allow methods execution
168 serv->Restrict("/log", "allow_method=Select,GetTitle");
169
170 // register exit command
171 serv->RegisterCommand("/Stop", "bRun=kFALSE;", "rootsys/icons/ed_delete.png");
172 serv->RegisterCommand("/ExitRoot", "gSystem->Exit(1);", "rootsys/icons/ed_delete.png");
173
174 // Fill histograms randomly
175 TRandom3 random;
176 Float_t px, py;
177 const Long_t kUPDATE = 1000;
178 Long_t cnt = 0;
179 while (bRun) {
180 random.Rannor(px, py);
181 hpx->Fill(px);
182 hpxpy->Fill(px, py);
183
184 // IMPORTANT: one should regularly call ProcessEvents
185 if (cnt++ % kUPDATE == 0) {
186 if (gSystem->ProcessEvents()) break;
187
188 Long_t loop = cnt / kUPDATE;
189
190 // make messages not very often
191 if (loop % 1000 == 0) {
192 loop = loop/1000;
193 int shift = loop % 40;
194 // make a 'stairs' with spaces
195 log->AddMsg(TString::Format("%*s Message %ld", shift, "", loop));
196 }
197 }
198 }
199
200}
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
long Long_t
Definition RtypesCore.h:54
float Float_t
Definition RtypesCore.h:57
long long Long64_t
Definition RtypesCore.h:69
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
#define ClassDefOverride(name, id)
Definition Rtypes.h:346
char name[80]
Definition TGX11.cxx:110
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
UInt_t Get() const
Return raw date/time as encoded by TDatime.
Definition TDatime.cxx:240
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:670
virtual void SetDirectory(TDirectory *dir)
By default, when a histogram is created, it is added to the list of histogram objects in the current ...
Definition TH1.cxx:8958
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition TH1.cxx:3344
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:307
Int_t Fill(Double_t) override
Invalid Fill method.
Definition TH2.cxx:393
Online http server for arbitrary ROOT application.
Definition THttpServer.h:31
A doubly linked list.
Definition TList.h:38
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:400
void Add(TObject *obj) override
Definition TList.h:81
TObject * Last() const override
Return the last object in the list. Returns 0 when list is empty.
Definition TList.cxx:691
void RemoveLast() override
Remove the last object of the list.
Definition TList.cxx:907
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:98
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
Collectable string class.
Definition TObjString.h:28
void SetString(const char *s)
Definition TObjString.h:45
Mother of all ROOT objects.
Definition TObject.h:41
Random number generator class based on M.
Definition TRandom3.h:27
virtual void Rannor(Float_t &a, Float_t &b)
Return 2 numbers distributed following a gaussian with mean=0 and sigma=1.
Definition TRandom.cxx:507
virtual Int_t GetLast() const
Returns index of last object in collection.
Basic string class.
Definition TString.h:139
static TString LLtoa(Long64_t value, Int_t base)
Converts a Long64_t to a TString with respect to the base specified (2-36).
Definition TString.cxx:2144
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1296
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:416
RVec< PromoteType< T > > log(const RVec< T > &v)
Definition RVec.hxx:1841
__device__ AFloat max(AFloat x, AFloat y)
Definition Kernels.cuh:207
const char * cnt
Definition TXMLSetup.cxx:75