Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RBrowserData.cxx
Go to the documentation of this file.
1// Author: Sergey Linev <S.Linev@gsi.de>
2// Date: 2019-10-14
3// Warning: This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
4
5/*************************************************************************
6 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#include <ROOT/RBrowserData.hxx>
14
21
22#include <ROOT/RLogger.hxx>
23
24#include "TFolder.h"
25#include "TROOT.h"
26#include "TBufferJSON.h"
27#include "TEnv.h"
28
29#include <algorithm>
30#include <regex>
31
32using namespace ROOT;
33using namespace std::string_literals;
34
36{
37 static ROOT::Experimental::RLogChannel sLog("ROOT.Browser");
38 return sLog;
39}
40
41namespace ROOT {
42
44
46
47public:
49
50 void RecursiveRemove(TObject *obj) override
51 {
53 }
54};
55
56} // namespace ROOT
57
58
59/** \class ROOT::RBrowserData
60\ingroup rbrowser
61\brief Way to browse (hopefully) everything in %ROOT
62*/
63
64
65/////////////////////////////////////////////////////////////////////
66/// Default constructor
67
69{
70 fCleanupHandle = std::make_unique<RBrowserDataCleanup>(*this);
72 gROOT->GetListOfCleanups()->Add(fCleanupHandle.get());
73}
74
75/////////////////////////////////////////////////////////////////////
76/// Destructor
77
79{
80 // should be here because of fCleanupHandle destructor
82 gROOT->GetListOfCleanups()->Remove(fCleanupHandle.get());
83}
84
85/////////////////////////////////////////////////////////////////////
86/// set top element for browsing
87
88void RBrowserData::SetTopElement(std::shared_ptr<Browsable::RElement> elem)
89{
90 fTopElement = elem;
91
93}
94
95/////////////////////////////////////////////////////////////////////
96/// set working directory relative to top element
97
99{
100 fWorkingPath = path;
101
103}
104
105/////////////////////////////////////////////////////////////////////
106/// Create default elements shown in the RBrowser
107
109{
110 auto comp = std::make_shared<Browsable::RGroup>("top","Root browser");
111
112 auto seldir = Browsable::RSysFile::ProvideTopEntries(comp);
113
114 std::unique_ptr<Browsable::RHolder> rootfold = std::make_unique<Browsable::TObjectHolder>(gROOT->GetRootFolder(), kFALSE);
115 auto elem_root = Browsable::RProvider::Browse(rootfold);
116 if (elem_root)
117 comp->Add(std::make_shared<Browsable::RWrapper>("root", elem_root));
118
119 std::unique_ptr<Browsable::RHolder> rootfiles = std::make_unique<Browsable::TObjectHolder>(gROOT->GetListOfFiles(), kFALSE);
120 auto elem_files = Browsable::RProvider::Browse(rootfiles);
121 if (elem_files) {
122 auto files = std::make_shared<Browsable::RWrapper>("ROOT Files", elem_files);
123 files->SetExpandByDefault(true);
124 comp->Add(files);
125 // if there are any open files, make them visible by default
126 if (elem_files->GetNumChilds() > 0)
127 seldir = {};
128 }
129
130 SetTopElement(comp);
131
132 SetWorkingPath(seldir);
133}
134
135/////////////////////////////////////////////////////////////////////
136/// Reset all data correspondent to last request
137
139{
140 fLastAllChilds = false;
141 fLastSortedItems.clear();
142 fLastSortMethod.clear();
143 fLastItems.clear();
144 if (with_element) {
145 fLastPath.clear();
146 fLastElement.reset();
147 }
148}
149
150/////////////////////////////////////////////////////////////////////////
151/// Decompose path to elements
152/// Returns array of names for each element in the path, first element either "/" or "."
153/// If returned array empty - it is error
154
155Browsable::RElementPath_t RBrowserData::DecomposePath(const std::string &strpath, bool relative_to_work_element)
156{
158 if (relative_to_work_element) arr = fWorkingPath;
159
160 if (strpath.empty())
161 return arr;
162
163 auto arr2 = Browsable::RElement::ParsePath(strpath);
164 arr.insert(arr.end(), arr2.begin(), arr2.end());
165 return arr;
166}
167
168/////////////////////////////////////////////////////////////////////////
169/// Process browser request
170
172{
173 auto path = fWorkingPath;
174 path.insert(path.end(), request.path.begin(), request.path.end());
175
176 if ((path != fLastPath) || !fLastElement) {
177
178 auto elem = GetSubElement(path);
179 if (!elem) return false;
180
182
183 fLastPath = path;
184 fLastElement = std::move(elem);
185
186 fLastElement->cd(); // set element active
187 } else if (request.reload) {
188 // only reload items from element, not need to reset element itself
190 }
191
192 // when request childs, always try to make elements
193 if (fLastItems.empty()) {
194
195 auto iter = fLastElement->GetChildsIter();
196
197 if (!iter) return false;
198 int id = 0;
199 fLastAllChilds = true;
200
201 while (iter->Next() && fLastAllChilds) {
202 fLastItems.emplace_back(iter->CreateItem());
203 if (id++ > 10000)
204 fLastAllChilds = false;
205 }
206
207 fLastSortedItems.clear();
208 fLastSortMethod.clear();
209 }
210
211 // create sorted array
212 if ((fLastSortedItems.size() != fLastItems.size()) ||
213 (fLastSortMethod != request.sort) ||
214 (fLastSortReverse != request.reverse)) {
215 fLastSortedItems.resize(fLastItems.size(), nullptr);
216 int id = 0;
217 if (request.sort.empty()) {
218 // no sorting, just move all folders up
219 for (auto &item : fLastItems)
220 if (item->IsFolder())
221 fLastSortedItems[id++] = item.get();
222 for (auto &item : fLastItems)
223 if (!item->IsFolder())
224 fLastSortedItems[id++] = item.get();
225 } else {
226 // copy items
227 for (auto &item : fLastItems)
228 fLastSortedItems[id++] = item.get();
229
230 if (request.sort != "unsorted")
231 std::sort(fLastSortedItems.begin(), fLastSortedItems.end(),
232 [request](const Browsable::RItem *a, const Browsable::RItem *b) { return a ? a->Compare(b, request.sort) : !b; });
233 }
234
235 if (request.reverse)
236 std::reverse(fLastSortedItems.begin(), fLastSortedItems.end());
237
238 fLastSortMethod = request.sort;
239 fLastSortReverse = request.reverse;
240 }
241
242 const std::regex expr(request.regex);
243
244 int id = 0;
245 for (auto &item : fLastSortedItems) {
246
247 // check if element is hidden
248 if (!request.hidden && item->IsHidden())
249 continue;
250
251 if (!request.regex.empty() && !item->IsFolder() && !std::regex_match(item->GetName(), expr))
252 continue;
253
254 if ((id >= request.first) && ((request.number == 0) || (id < request.first + request.number)))
255 reply.nodes.emplace_back(item);
256
257 id++;
258 }
259
260 reply.first = request.first;
261 reply.nchilds = id; // total number of childs
262
263 return true;
264}
265
266/////////////////////////////////////////////////////////////////////////
267/// Process browser request, returns string with JSON of RBrowserReply data
268
270{
271 if (request.lastcycle < 0)
272 gEnv->SetValue("WebGui.LastCycle", "no");
273 else if (request.lastcycle > 0)
274 gEnv->SetValue("WebGui.LastCycle", "yes");
275
276 RBrowserReply reply;
277
278 reply.path = request.path;
279 reply.first = 0;
280 reply.nchilds = 0;
281
282 ProcessBrowserRequest(request, reply);
283
285}
286
287/////////////////////////////////////////////////////////////////////////
288/// Returns element with path, specified as string
289
290std::shared_ptr<Browsable::RElement> RBrowserData::GetElement(const std::string &str)
291{
292 auto path = DecomposePath(str, true);
293
294 return GetSubElement(path);
295}
296
297/////////////////////////////////////////////////////////////////////////
298/// Returns element with path, specified as Browsable::RElementPath_t
299
300std::shared_ptr<Browsable::RElement> RBrowserData::GetElementFromTop(const Browsable::RElementPath_t &path)
301{
302 return GetSubElement(path);
303}
304
305/////////////////////////////////////////////////////////////////////////
306/// Returns sub-element starting from top, using cached data
307
308std::shared_ptr<Browsable::RElement> RBrowserData::GetSubElement(const Browsable::RElementPath_t &path)
309{
310 if (path.empty())
311 return fTopElement;
312
313 // validate cache - removes no longer actual elements
314 RemoveFromCache(nullptr);
315
316 // first check direct match in cache
317 for (auto &entry : fCache)
318 if (entry.first == path)
319 return entry.second;
320
321 // find best possible entry in cache
322 int pos = 0;
323 auto elem = fTopElement;
324
325 for (auto &entry : fCache) {
326 if (entry.first.size() >= path.size())
327 continue;
328
329 auto comp = Browsable::RElement::ComparePaths(path, entry.first);
330
331 if ((comp > pos) && (comp == (int) entry.first.size())) {
332 pos = comp;
333 elem = entry.second;
334 }
335 }
336
337 while (pos < (int) path.size()) {
338 std::string subname = path[pos];
339 int indx = Browsable::RElement::ExtractItemIndex(subname);
340
341 auto iter = elem->GetChildsIter();
342 if (!iter)
343 return nullptr;
344
345 if (!iter->Find(subname, indx)) {
346 if (indx < 0)
347 return nullptr;
348 iter = elem->GetChildsIter();
349 if (!iter || !iter->Find(subname))
350 return nullptr;
351 }
352
353 elem = iter->GetElement();
354
355 if (!elem)
356 return nullptr;
357
358 auto subpath = path;
359 subpath.resize(pos+1);
360 fCache.emplace_back(subpath, elem);
361 pos++; // switch to next element
362 }
363
364 return elem;
365}
366
367/////////////////////////////////////////////////////////////////////////
368/// Clear internal objects cache
369
371{
372 fCache.clear();
373}
374
375/////////////////////////////////////////////////////////////////////////
376/// Remove object from cache
377/// If nullptr specified - removes no-longer-valid elements
378/// Returns true if any element was removed
379
381{
382 unsigned pos = 0;
383
384 bool isany = false;
385
386 while (pos < fCache.size()) {
387 if (obj ? !fCache[pos].second->IsObject(obj) : fCache[pos].second->CheckValid()) {
388 pos++;
389 continue;
390 }
391
392 isany = true;
393 auto path = fCache[pos].first;
394 fCache.erase(fCache.begin() + pos);
395 if (RemoveFromCache(path))
396 pos = 0; // start scan from the beginning
397 }
398
399 return isany;
400}
401
402/////////////////////////////////////////////////////////////////////////
403/// Remove path (and all sub-paths) from cache
404/// Returns true if any element was removed
405
407{
408 if (path.size() == 0)
409 return false;
410
411 bool isany = false;
412 unsigned pos = 0;
413 while (pos < fCache.size()) {
414 if (Browsable::RElement::ComparePaths(path, fCache[pos].first) == (int) path.size()) {
415 fCache.erase(fCache.begin() + pos);
416 isany = true;
417 } else {
418 pos++;
419 }
420 }
421 return isany;
422}
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
#define R__LOCKGUARD(mutex)
static int ExtractItemIndex(std::string &name)
Extract index from name Index coded by client with ###<indx>$$$ suffix Such coding used by browser to...
Definition RElement.cxx:178
static int ComparePaths(const RElementPath_t &path1, const RElementPath_t &path2)
Compare two paths, Returns number of elements matches in both paths.
Definition RElement.cxx:145
static RElementPath_t ParsePath(const std::string &str)
Parse string path to produce RElementPath_t One should avoid to use string pathes as much as possible...
Definition RElement.cxx:116
Representation of single item in the browser.
Definition RItem.hxx:23
static std::shared_ptr< RElement > Browse(std::unique_ptr< RHolder > &obj)
Create browsable element for the object Created element may take ownership over the object.
static RElementPath_t ProvideTopEntries(std::shared_ptr< RGroup > &comp, const std::string &workdir="")
Provide top entries for file system On windows it is list of existing drivers, on Linux it is "File s...
Definition RSysFile.cxx:533
A log configuration for a channel, e.g.
Definition RLogger.hxx:101
RBrowserDataCleanup(RBrowserData &_data)
void RecursiveRemove(TObject *obj) override
Recursively remove this object from a list.
Way to browse (hopefully) everything in ROOT.
void SetTopElement(std::shared_ptr< Browsable::RElement > elem)
set top element for browsing
std::vector< const Browsable::RItem * > fLastSortedItems
! sorted child items, used in requests
Browsable::RElementPath_t fWorkingPath
! path showed in Breadcrumb
bool RemoveFromCache(void *obj)
Remove object from cache If nullptr specified - removes no-longer-valid elements Returns true if any ...
std::shared_ptr< Browsable::RElement > GetSubElement(const Browsable::RElementPath_t &path)
Returns sub-element starting from top, using cached data.
std::vector< std::pair< Browsable::RElementPath_t, std::shared_ptr< Browsable::RElement > > > fCache
! already requested elements
std::unique_ptr< TObject > fCleanupHandle
! cleanup handle for RecursiveRemove
Browsable::RElementPath_t DecomposePath(const std::string &path, bool relative_to_work_element)
Decompose path to elements Returns array of names for each element in the path, first element either ...
bool fLastAllChilds
! if all chlds were extracted
virtual ~RBrowserData()
Destructor.
bool ProcessBrowserRequest(const RBrowserRequest &request, RBrowserReply &reply)
Process browser request.
std::shared_ptr< Browsable::RElement > GetElementFromTop(const Browsable::RElementPath_t &path)
Returns element with path, specified as Browsable::RElementPath_t.
std::string fLastSortMethod
! last sort method
void ClearCache()
Clear internal objects cache.
std::string ProcessRequest(const RBrowserRequest &request)
Process browser request, returns string with JSON of RBrowserReply data.
std::vector< std::unique_ptr< Browsable::RItem > > fLastItems
! created browser items - used in requests
Browsable::RElementPath_t fLastPath
! path to last used element
void SetWorkingPath(const Browsable::RElementPath_t &path)
set working directory relative to top element
std::shared_ptr< Browsable::RElement > fTopElement
! top element
std::shared_ptr< Browsable::RElement > GetElement(const std::string &str)
Returns element with path, specified as string.
bool fLastSortReverse
! last request reverse order
void ResetLastRequestData(bool with_element)
Reset all data correspondent to last request.
std::shared_ptr< Browsable::RElement > fLastElement
! last element used in request
void CreateDefaultElements()
Create default elements shown in the RBrowser.
RBrowserData()
Default constructor.
Reply on browser request.
std::vector< std::string > path
reply path
std::vector< const Browsable::RItem * > nodes
list of pointers, no ownership!
int first
first node in returned list
int nchilds
total number of childs in the node
Request send from client to get content of path element.
int lastcycle
show only last cycle, -1 - off, 0 - not change, +1 on,
bool hidden
show hidden files
int number
number of childs to request, 0 - all childs
bool reverse
reverse item order
std::string sort
kind of sorting
std::vector< std::string > path
requested path
bool reload
force items reload
int first
first child to request
std::string regex
applied regex
static TString ToJSON(const T *obj, Int_t compact=0, const char *member_name=nullptr)
Definition TBufferJSON.h:75
@ kSkipTypeInfo
do not store typenames in JSON
Definition TBufferJSON.h:48
@ kNoSpaces
no new lines plus remove all spaces around "," and ":" symbols
Definition TBufferJSON.h:39
virtual void SetValue(const char *name, const char *value, EEnvLevel level=kEnvChange, const char *type=nullptr)
Set the value of a resource or create a new resource.
Definition TEnv.cxx:736
Mother of all ROOT objects.
Definition TObject.h:41
const char * Data() const
Definition TString.h:376
std::vector< std::string > RElementPath_t
Definition RElement.hxx:20
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
ROOT::Experimental::RLogChannel & BrowserLog()
Log channel for Browser diagnostics.