Logo ROOT  
Reference Guide
TProofMgr.cxx
Go to the documentation of this file.
1// @(#)root/proof:$Id$
2// Author: G. Ganis, Nov 2005
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TProofMgr
13\ingroup proofkernel
14
15The PROOF manager interacts with the PROOF server coordinator to
16create or destroy a PROOF session, attach to or detach from
17existing one, and to monitor any client activity on the cluster.
18At most one manager instance per server is allowed.
19
20*/
21
22#include "Bytes.h"
23#include "TError.h"
24#include "TEnv.h"
25#include "TFile.h"
26#include "TFileCollection.h"
27#include "TFileInfo.h"
28#include "TList.h"
29#include "TParameter.h"
30#include "TProof.h"
31#include "TProofMgr.h"
32#include "TProofMgrLite.h"
33#include "TSocket.h"
34#include "TROOT.h"
35#include "TMath.h"
36#include "TObjString.h"
37
39
40// Sub-list of TROOT::fProofs with managers
43
44// Auxilliary structures for pinging
45// The client request
46typedef struct {
47 int first;
48 int second;
49 int third;
50 int fourth;
51 int fifth;
52} clnt_HS_t;
53// The body received after the first handshake's header
54typedef struct {
55 int msglen;
56 int protover;
57 int msgval;
58} srv_HS_t;
59
60////////////////////////////////////////////////////////////////////////////////
61/// Create a PROOF manager for the standard (old) environment.
62
63TProofMgr::TProofMgr(const char *url, Int_t, const char *alias)
64 : TNamed("",""), fRemoteProtocol(-1), fServType(kXProofd),
65 fSessions(0), fIntHandler(0)
66{
68
69 // AVoid problems with empty URLs
70 fUrl = (!url || strlen(url) <= 0) ? TUrl("proof://localhost") : TUrl(url);
71
72 // Correct URL protocol
73 if (!strcmp(fUrl.GetProtocol(), TUrl("a").GetProtocol()))
74 fUrl.SetProtocol("proof");
75
76 // Check port
77 if (fUrl.GetPort() == TUrl("a").GetPort()) {
78 // For the time being we use 'rootd' service as default.
79 // This will be changed to 'proofd' as soon as XRD will be able to
80 // accept on multiple ports
81 Int_t port = gSystem->GetServiceByName("proofd");
82 if (port < 0) {
83 if (gDebug > 0)
84 Info("TProofMgr","service 'proofd' not found by GetServiceByName"
85 ": using default IANA assigned tcp port 1093");
86 port = 1093;
87 } else {
88 if (gDebug > 1)
89 Info("TProofMgr","port from GetServiceByName: %d", port);
90 }
91 fUrl.SetPort(port);
92 }
93
94 // Check and save the host FQDN ...
95 if (strcmp(fUrl.GetHost(), "__lite__")) {
96 if (strcmp(fUrl.GetHost(), fUrl.GetHostFQDN()))
98 }
99
101 if (alias)
102 SetAlias(alias);
103 else
105}
106
107////////////////////////////////////////////////////////////////////////////////
108/// Destroy a TProofMgr instance
109
111{
114
116 gROOT->GetListOfProofs()->Remove(this);
117}
118
119////////////////////////////////////////////////////////////////////////////////
120/// Dummy version provided for completeness. Just returns a pointer to
121/// existing session 'id' (as shown by TProof::QuerySessions) or 0 if 'id' is
122/// not valid. The boolena 'gui' should be kTRUE when invoked from the GUI.
123
125{
127 if (d)
128 return AttachSession(d, gui);
129
130 Info("AttachSession","invalid proofserv id (%d)", id);
131 return 0;
132}
133
134////////////////////////////////////////////////////////////////////////////////
135/// Dummy version provided for completeness. Just returns a pointer to
136/// existing session 'id' (as shown by TProof::QuerySessions) or 0 if 'id' is
137/// not valid.
138
140{
141 if (!d) {
142 Warning("AttachSession","invalid description object - do nothing");
143 return 0;
144 }
145
146 if (d->GetProof())
147 // Nothing to do if already in contact with proofserv
148 return d->GetProof();
149
150 Warning("AttachSession","session not available - do nothing");
151 return 0;
152}
153
154////////////////////////////////////////////////////////////////////////////////
155/// Detach session with 'id' from its proofserv. The 'id' is the number
156/// shown by QuerySessions. The correspondent TProof object is deleted.
157/// If id == 0 all the known sessions are detached.
158/// Option opt="S" or "s" forces session shutdown.
159
161{
162 if (!IsValid()) {
163 Warning("DetachSession","invalid TProofMgr - do nothing");
164 return;
165 }
166
167 if (id > 0) {
168
170 if (d) {
171 if (d->GetProof())
172 d->GetProof()->Detach(opt);
173 TProof *p = d->GetProof();
175 SafeDelete(p);
176 delete d;
177 }
178
179 } else if (id == 0) {
180
181 // Requesto to destroy all sessions
182 if (fSessions) {
183 // Delete PROOF sessions
184 TIter nxd(fSessions);
185 TProofDesc *d = 0;
186 while ((d = (TProofDesc *)nxd())) {
187 if (d->GetProof())
188 d->GetProof()->Detach(opt);
189 TProof *p = d->GetProof();
191 SafeDelete(p);
192 }
193 fSessions->Delete();
194 }
195 }
196
197 return;
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// Detach session 'p' from its proofserv. The instance 'p' is invalidated
202/// and should be deleted by the caller
203
205{
206 if (!IsValid()) {
207 Warning("DetachSession","invalid TProofMgr - do nothing");
208 return;
209 }
210
211 if (p) {
212 // Single session request
214 if (d) {
215 if (d->GetProof())
216 // The session is closed here
217 d->GetProof()->Detach(opt);
219 delete d;
220 }
221 }
222
223 return;
224}
225
226////////////////////////////////////////////////////////////////////////////////
227/// Get list of sessions accessible to this manager.
228
230{
231 if (opt && !strncasecmp(opt,"L",1))
232 // Just return the existing list
233 return fSessions;
234
235 // Create list if not existing
236 if (!fSessions) {
237 fSessions = new TList();
239 }
240
241 // Fill-in entries from the official list
242 if (gROOT->GetListOfProofs()) {
243 // Loop over
244 TIter nxp(gROOT->GetListOfProofs());
245 TObject *o = 0;
246 TProof *p = 0;
247 Int_t ns = 0;
248 while ((o = nxp())) {
249 if (o->InheritsFrom(TProof::Class())) {
250 p = (TProof *)o;
251 // Only those belonging to this server
252 if (MatchUrl(p->GetUrl())) {
253 if (!(fSessions->FindObject(p->GetSessionTag()))) {
254 Int_t st = (p->IsIdle()) ? TProofDesc::kIdle
256 TProofDesc *d =
257 new TProofDesc(p->GetName(), p->GetTitle(), p->GetUrl(),
258 ++ns, p->GetSessionID(), st, p);
259 fSessions->Add(d);
260 }
261 }
262 }
263 }
264 }
265
266 // Drop entries not existing any longer
267 if (fSessions->GetSize() > 0) {
268 TIter nxd(fSessions);
269 TProofDesc *d = 0;
270 while ((d = (TProofDesc *)nxd())) {
271 if (d->GetProof()) {
272 if (!(gROOT->GetListOfProofs()->FindObject(d->GetProof()))) {
274 SafeDelete(d);
275 } else {
276 if (opt && !strncasecmp(opt,"S",1))
277 d->Print("");
278 }
279 }
280 }
281 }
282
283 // We are done
284 return fSessions;
285}
286
287////////////////////////////////////////////////////////////////////////////////
288/// Send a message to connected users. Only superusers can do this.
289/// The first argument specifies the message or the file from where to take
290/// the message.
291/// The second argument specifies the user to which to send the message: if
292/// empty or null the message is send to all the connected users.
293/// return 0 in case of success, -1 in case of error
294
295Int_t TProofMgr::SendMsgToUsers(const char *, const char *)
296{
297 Warning("SendMsgToUsers","functionality not supported");
298
299 return -1;
300}
301
302////////////////////////////////////////////////////////////////////////////////
303/// Send a cleanup request for the sessions associated with the current
304/// user.
305/// Not supported.
306
308{
309 Warning("Reset","functionality not supported");
310
311 return -1;
312}
313
314////////////////////////////////////////////////////////////////////////////////
315/// Show available workers
316
318{
319 AbstractMethod("ShowWorkers");
320}
321
322////////////////////////////////////////////////////////////////////////////////
323/// Get TProofDesc instance corresponding to 'id'.
324
326{
327 TProofDesc *d = 0;
328 if (id > 0) {
329 // Retrieve an updated list
330 QuerySessions("");
331 if (fSessions) {
332 TIter nxd(fSessions);
333 while ((d = (TProofDesc *)nxd())) {
334 if (d->MatchId(id))
335 return d;
336 }
337 }
338 }
339
340 return d;
341}
342
343////////////////////////////////////////////////////////////////////////////////
344/// Get TProofDesc instance corresponding to TProof object 'p'.
345
347{
348 TProofDesc *d = 0;
349 if (p) {
350 // Retrieve an updated list
351 QuerySessions("");
352 if (fSessions) {
353 TIter nxd(fSessions);
354 while ((d = (TProofDesc *)nxd())) {
355 if (p == d->GetProof())
356 return d;
357 }
358 }
359 }
360
361 return d;
362}
363
364////////////////////////////////////////////////////////////////////////////////
365/// Discard TProofDesc of session 'p' from the internal list
366
368{
369 if (p) {
370 TProofDesc *d = 0;
371 if (fSessions) {
372 TIter nxd(fSessions);
373 while ((d = (TProofDesc *)nxd())) {
374 if (p == d->GetProof()) {
376 delete d;
377 break;
378 }
379 }
380 }
381 }
382}
383
384////////////////////////////////////////////////////////////////////////////////
385/// Create a new remote session (master and associated workers).
386
388 const char *cfgdir, Int_t loglevel)
389{
390 // Create
391 if (IsProofd())
392 fUrl.SetOptions("std");
393
394 // Create the instance
395 TProof *p = new TProof(fUrl.GetUrl(), cfg, cfgdir, loglevel, 0, this);
396
397 if (p && p->IsValid()) {
398
399 // Save record about this session
400 Int_t ns = 1;
401 if (fSessions) {
402 // To avoid ambiguities in case of removal of some elements
403 if (fSessions->Last())
404 ns = ((TProofDesc *)(fSessions->Last()))->GetLocalId() + 1;
405 } else {
406 // Create the list
407 fSessions = new TList;
408 }
409
410 // Create the description class
412 TProofDesc *d =
413 new TProofDesc(p->GetName(), p->GetTitle(), p->GetUrl(),
414 ns, p->GetSessionID(), st, p);
415 fSessions->Add(d);
416
417 } else {
418 // Session creation failed
419 if (gDebug > 0) Error("CreateSession", "PROOF session creation failed");
420 SafeDelete(p);
421 }
422
423 // We are done
424 return p;
425}
426
427////////////////////////////////////////////////////////////////////////////////
428/// Checks if 'url' refers to the same 'user@host:port' entity as the URL
429/// in memory
430
432{
433 TUrl u(url);
434
435 // Correct URL protocol
436 if (!strcmp(u.GetProtocol(), TUrl("a").GetProtocol()))
437 u.SetProtocol("proof");
438
439 // Correct port
440 if (u.GetPort() == TUrl("a").GetPort()) {
441 Int_t port = gSystem->GetServiceByName("proofd");
442 if (port < 0)
443 port = 1093;
444 u.SetPort(port);
445 }
446
447 // Now we can check
448 if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN()))
449 if (u.GetPort() == fUrl.GetPort())
450 if (strlen(u.GetUser()) <= 0 || !strcmp(u.GetUser(),fUrl.GetUser()))
451 return kTRUE;
452
453 // Match failed
454 return kFALSE;
455}
456
457////////////////////////////////////////////////////////////////////////////////
458/// Extract pointers to PROOF managers from TROOT::fProofs.
459
461{
462 // Update the list with new entries
463 if (gROOT->GetListOfProofs()) {
464 TIter nxp(gROOT->GetListOfProofs());
465 TObject *o = 0;
466 while ((o = nxp())) {
469 }
470 }
471
472 // Get rid of invalid entries and notify
473 if (fgListOfManagers.GetSize() > 0) {
475 TObject *o = 0;
476 Int_t nm = 0;
477 while ((o = nxp())) {
478 if (!(gROOT->GetListOfProofs()->FindObject(o))) {
480 } else {
481 TProofMgr *p = (TProofMgr *)o;
482 if (gDebug > 0)
483 Printf("// #%d: \"%s\" (%s)", ++nm, p->GetName(), p->GetTitle());
484 }
485 }
486 } else {
487 if (gDebug > 0)
488 Printf("No managers found");
489 }
490
491 // We are done
492 return &fgListOfManagers;
493}
494
495////////////////////////////////////////////////////////////////////////////////
496/// Static method returning the appropriate TProofMgr object using
497/// the plugin manager.
498
499TProofMgr *TProofMgr::Create(const char *uin, Int_t loglevel,
500 const char *alias, Bool_t xpd)
501{
502 TProofMgr *m= 0;
503
504 Bool_t isLite = kFALSE;
505
506 // Resolve url; if empty the actions depend of the default
507 TUrl u(uin);
509 if (proto.IsNull()) {
510 u.SetUrl(gEnv->GetValue("Proof.LocalDefault", "lite://"));
511 proto = u.GetProtocol();
512 }
513 TString host = u.GetHost();
514 if (proto == "lite" || host == "__lite__" ) {
515#ifndef WIN32
516 isLite = kTRUE;
517 u.SetHost("__lite__");
518 u.SetProtocol("proof");
519 u.SetPort(1093);
520#else
521 ::Info("TProofMgr::Create","'lite' not yet supported on Windows");
522 return m;
523#endif
524 }
525
526 if (!isLite) {
527 // in case user gave as url: "machine.dom.ain", replace
528 // "http" by "proof" and "80" by "1093"
529 if (!strcmp(u.GetProtocol(), TUrl("a").GetProtocol()))
530 u.SetProtocol("proof");
531 if (u.GetPort() == TUrl("a").GetPort())
532 u.SetPort(1093);
533 }
534
535 // Avoid multiple calls to GetUrl
536 const char *url = u.GetUrl();
537
538 // Make sure we do not have already a manager for this URL
540 if (lm) {
541 TIter nxm(lm);
542 while ((m = (TProofMgr *)nxm())) {
543 if (m->IsValid()) {
544 if (m->MatchUrl(url)) return m;
545 } else {
547 SafeDelete(m);
548 break;
549 }
550 }
551 }
552
553 if (isLite) {
554 // Init the lite version
555 return new TProofMgrLite(url, loglevel, alias);
556 }
557
558 m = 0;
559 Bool_t trystd = kTRUE;
560
561 // If required, we assume first that the remote server is based on XrdProofd
562 if (xpd) {
564 if (cm) {
565 m = (TProofMgr *) (*cm)(url, loglevel, alias);
566 // Update trystd flag
567 trystd = (m && !(m->IsValid()) && m->IsProofd()) ? kTRUE : kFALSE;
568 }
569 }
570
571 // If the first attempt failed, we instantiate an old interface
572 if (trystd) {
573 SafeDelete(m);
574 m = new TProofMgr(url, loglevel, alias);
575 }
576
577 // Record the new manager, if any
578 if (m) {
580 if (m->IsValid() && !(m->IsProofd())) {
582 gROOT->GetListOfProofs()->Add(m);
583 gROOT->GetListOfSockets()->Add(m);
584 }
585 }
586
587 // We are done
588 return m;
589}
590
591////////////////////////////////////////////////////////////////////////////////
592/// Get the constructor hook fro TXProofMgr.
593/// We do this without the plugin manager because it blocks the
594/// CINT mutex breaking the parallel startup.
595
597{
598 if (!fgTXProofMgrHook) {
599 // Load the appropriate library ...
600 TString prooflib = "libProofx";
601 char *p = 0;
602 if ((p = gSystem->DynamicPathName(prooflib, kTRUE))) {
603 delete[] p;
604 if (gSystem->Load(prooflib) == -1)
605 ::Error("TProofMgr::GetXProofMgrCtor",
606 "can't load %s", prooflib.Data());
607 } else
608 ::Error("TProofMgr::GetXProofMgrCtor",
609 "can't locate %s", prooflib.Data());
610 }
611
612 // Done
613 return fgTXProofMgrHook;
614}
615
616////////////////////////////////////////////////////////////////////////////////
617/// Set hook to TXProofMgr ctor
618
620{
621 fgTXProofMgrHook = pmh;
622}
623
624////////////////////////////////////////////////////////////////////////////////
625/// Non-blocking check for a PROOF (or Xrootd, if checkxrd) service at 'url'
626/// Return
627/// 0 if a XProofd (or Xrootd, if checkxrd) daemon is listening at 'url'
628/// -1 if nothing is listening on the port (connection cannot be open)
629/// 1 if something is listening but not XProofd (or not Xrootd, if checkxrd)
630
631Int_t TProofMgr::Ping(const char *url, Bool_t checkxrd)
632{
633 if (!url || (url && strlen(url) <= 0)) {
634 ::Error("TProofMgr::Ping", "empty url - fail");
635 return -1;
636 }
637
638 TUrl u(url);
639 // Check the port and set the defaults
640 if (!strcmp(u.GetProtocol(), "http") && u.GetPort() == 80) {
641 if (!checkxrd) {
642 u.SetPort(1093);
643 } else {
644 u.SetPort(1094);
645 }
646 }
647
648 // Open the connection, disabling warnings ...
649 Int_t oldLevel = gErrorIgnoreLevel;
651 TSocket s(u.GetHost(), u.GetPort());
652 if (!(s.IsValid())) {
653 if (gDebug > 0)
654 ::Info("TProofMgr::Ping", "could not open connection to %s:%d", u.GetHost(), u.GetPort());
655 gErrorIgnoreLevel = oldLevel;
656 return -1;
657 }
658 // Send the first bytes
659 int writeCount = -1;
660 clnt_HS_t initHS;
661 memset(&initHS, 0, sizeof(initHS));
662 int len = sizeof(initHS);
663 if (checkxrd) {
664 initHS.fourth = (int)host2net((int)4);
665 initHS.fifth = (int)host2net((int)2012);
666 if ((writeCount = s.SendRaw(&initHS, len)) != len) {
667 if (gDebug > 0)
668 ::Info("TProofMgr::Ping", "1st: wrong number of bytes sent: %d (expected: %d)",
669 writeCount, len);
670 gErrorIgnoreLevel = oldLevel;
671 return 1;
672 }
673 } else {
674 initHS.third = (int)host2net((int)1);
675 if ((writeCount = s.SendRaw(&initHS, len)) != len) {
676 if (gDebug > 0)
677 ::Info("TProofMgr::Ping", "1st: wrong number of bytes sent: %d (expected: %d)",
678 writeCount, len);
679 gErrorIgnoreLevel = oldLevel;
680 return 1;
681 }
682 // These 8 bytes are need by 'proofd' and discarded by XPD
683 int dum[2];
684 dum[0] = (int)host2net((int)4);
685 dum[1] = (int)host2net((int)2012);
686 if ((writeCount = s.SendRaw(&dum[0], sizeof(dum))) != sizeof(dum)) {
687 if (gDebug > 0)
688 ::Info("TProofMgr::Ping", "2nd: wrong number of bytes sent: %d (expected: %d)",
689 writeCount, (int) sizeof(dum));
690 gErrorIgnoreLevel = oldLevel;
691 return 1;
692 }
693 }
694 // Read first server response
695 int type;
696 len = sizeof(type);
697 int readCount = s.RecvRaw(&type, len); // 4(2+2) bytes
698 if (readCount != len) {
699 if (gDebug > 0)
700 ::Info("TProofMgr::Ping", "1st: wrong number of bytes read: %d (expected: %d)",
701 readCount, len);
702 gErrorIgnoreLevel = oldLevel;
703 return 1;
704 }
705 // to host byte order
706 type = net2host(type);
707 // Check if the server is the eXtended proofd
708 if (type == 0) {
709 srv_HS_t xbody;
710 len = sizeof(xbody);
711 readCount = s.RecvRaw(&xbody, len); // 12(4+4+4) bytes
712 if (readCount != len) {
713 if (gDebug > 0)
714 ::Info("TProofMgr::Ping", "2nd: wrong number of bytes read: %d (expected: %d)",
715 readCount, len);
716 gErrorIgnoreLevel = oldLevel;
717 return 1;
718 }
719 xbody.protover = net2host(xbody.protover);
720 xbody.msgval = net2host(xbody.msglen);
721 xbody.msglen = net2host(xbody.msgval);
722
723 } else if (type == 8) {
724 // Standard proofd
725 if (gDebug > 0) ::Info("TProofMgr::Ping", "server is old %s", (checkxrd ? "ROOTD" : "PROOFD"));
726 gErrorIgnoreLevel = oldLevel;
727 return 1;
728 } else {
729 // We don't know the server type
730 if (gDebug > 0) ::Info("TProofMgr::Ping", "unknown server type: %d", type);
731 gErrorIgnoreLevel = oldLevel;
732 return 1;
733 }
734
735 // Restore ignore level
736 gErrorIgnoreLevel = oldLevel;
737 // Done
738 return 0;
739}
740
741////////////////////////////////////////////////////////////////////////////////
742/// Parse file name extracting the directory subcomponents in dirs, stored
743/// as TObjStrings.
744
745void TProofMgr::ReplaceSubdirs(const char *fn, TString &fdst, TList &dirph)
746{
747 if (!fn || (fn && strlen(fn) <= 0)) return;
748 if (dirph.GetSize() <= 0) return;
749
750 // Parse fn
751 TList dirs;
752 TString dd(fn), d;
753 Ssiz_t from = 0;
754 while (dd.Tokenize(d, from, "/")) {
755 if (!d.IsNull()) dirs.Add(new TObjString(d));
756 }
757 if (dirs.GetSize() <= 0) return;
758 dirs.SetOwner(kTRUE);
759
760 TIter nxph(&dirph);
762 while ((pi = (TParameter<Int_t> *) nxph())) {
763 if (pi->GetVal() < dirs.GetSize()) {
764 TObjString *os = (TObjString *) dirs.At(pi->GetVal());
765 if (os) fdst.ReplaceAll(pi->GetName(), os->GetName());
766 } else {
767 ::Warning("TProofMgr::ReplaceSubdirs",
768 "requested directory level '%s' is not available in the file path",
769 pi->GetName());
770 }
771 }
772}
773
774////////////////////////////////////////////////////////////////////////////////
775/// Upload files provided via the list 'src' (as TFileInfo or TObjString)
776/// to 'mss'. The path under 'mss' is determined by 'dest'; the following
777/// place-holders can be used in 'dest':
778/// <d0>, <d1>, <d2>, ... referring to the n-th sub-component
779/// of the src path
780/// <bn> basename in the source path
781/// <bs> basename sans extension
782/// <ex> Extension
783/// <sn> serial number of file in the list
784/// <s0> as <sn> but zero padded
785/// <fn> the full file path
786/// <us>, <gr> the local user and group names.
787/// <pg> the users PROOF group
788/// <pa> immediate parent directory
789/// <gp> next-to immediate parent directory
790/// So, for example, if the source filename for the 99-th file is
791/// protosrc://host//d0/d1/d2/d3/d4/d5/myfile
792/// then with dest = '/pool/user/<d3>/<d4>/<d5>/<s>/<bn>' and
793/// mss = 'protodst://hostdst//nm/
794/// the corresponding destination path is
795/// protodst://hostdst//nm/pool/user/d3/d4/d5/99/myfile
796///
797/// If 'dest' is empty, <fn> is used.
798///
799/// Returns a TFileCollection with the destination files created; this
800/// TFileCollection is, for example, ready to be registered as dataset.
801
803 const char *mss, const char *dest)
804{
805 TFileCollection *ds = 0;
806
807 // The inputs must be make sense
808 if (!src || (src && src->GetSize() <= 0)) {
809 ::Warning("TProofMgr::UploadFiles", "list is empty!");
810 return ds;
811 }
812 if (!mss || (mss && strlen(mss) <= 0)) {
813 ::Warning("TProofMgr::UploadFiles", "MSS is undefined!");
814 return ds;
815 }
816
817 TList dirph;
818
819 // If the destination is defined we need to understand if we have place-holders
820 if (dest && strlen(dest) > 0) {
821 TString dst(dest), dt;
822 Ssiz_t from = 0;
823 TRegexp re("<d+[0-9]>");
824 while (dst.Tokenize(dt, from, "/")) {
825 if (dt.Contains(re)) {
827 dt.ReplaceAll("<d", "");
828 dt.ReplaceAll(">", "");
829 if (dt.IsDigit()) {
830 pi->SetVal(dt.Atoi());
831 dirph.Add(pi);
832 } else {
833 SafeDelete(pi);
834 }
835 }
836 }
837 dirph.SetOwner(kTRUE);
838 }
839 // Generate template for zero-padded serial numbers
840 TString sForm = TString::Format("%%0%dd",
841 Int_t(TMath::Log10(src->GetEntries()+1)));
842
843 // Now we will actually copy files and create the TList object
844 ds = new TFileCollection();
845 TIter nxf(src);
846 TObject *o = 0;
847 TObjString *os = 0;
848 TFileInfo *fi = 0;
849 Int_t kn = 0;
850 while ((o = nxf())) {
851 TUrl *furl = 0;
852 if (!strcmp(o->ClassName(), "TFileInfo")) {
853 if (!(fi = dynamic_cast<TFileInfo *>(o))) {
854 ::Warning("TProofMgr::UploadFiles",
855 "object of class name '%s' does not cast to %s - ignore",
856 o->ClassName(), o->ClassName());
857 continue;
858 }
859 furl = fi->GetFirstUrl();
860 } else if (!strcmp(o->ClassName(), "TObjString")) {
861 if (!(os = dynamic_cast<TObjString *>(o))) {
862 ::Warning("TProofMgr::UploadFiles",
863 "object of class name '%s' does not cast to %s - ignore",
864 o->ClassName(), o->ClassName());
865 continue;
866 }
867 furl = new TUrl(os->GetName());
868 } else {
869 ::Warning("TProofMgr::UploadFiles",
870 "object of unsupported class '%s' found in list - ignore", o->ClassName());
871 continue;
872 }
873
874 // The file must be accessible
875 if (gSystem->AccessPathName(furl->GetUrl()) == kFALSE) {
876
877 // Create the destination path
878 TString fdst(mss);
879 if (dest && strlen(dest) > 0) {
880 fdst += dest;
881 } else {
882 fdst += TString::Format("/%s", furl->GetFile());
883 }
884
885 // Replace filename and basename
886 if (fdst.Contains("<bn>")) fdst.ReplaceAll("<bn>", gSystem->BaseName(furl->GetFile()));
887 if (fdst.Contains("<fn>")) fdst.ReplaceAll("<fn>", furl->GetFile());
888 if (fdst.Contains("<bs>")) {
889 // Basename sans 'extension'
890 TString bs(gSystem->BaseName(furl->GetFile()));
891 Int_t idx = bs.Last('.');
892 if (idx != kNPOS) bs.Remove(idx);
893 fdst.ReplaceAll("<bs>", bs.Data());
894 }
895 if (fdst.Contains("<ex>")) {
896 // 'Extension' - that is the last part after the last '.'
897 TString ex(furl->GetFile());
898 Int_t idx = ex.Last('.');
899 if (idx != kNPOS) ex.Remove(0, idx+1);
900 else ex = "";
901 fdst.ReplaceAll("<ex>", ex);
902 }
903 if (fdst.Contains("<pa>")) {
904 fdst.ReplaceAll("<pa>",
906 ->DirName(furl->GetFile())));
907
908 }
909 if (fdst.Contains("<gp>")) {
910 fdst.ReplaceAll("<gp>",
913 ->DirName(furl->GetFile()))));
914
915 }
916
917
918 // Replace serial number
919 if (fdst.Contains("<sn>")) {
920 TString skn = TString::Format("%d", kn);
921 fdst.ReplaceAll("<sn>", skn);
922 }
923 if (fdst.Contains("<s0>")) {
924 TString skn = TString::Format(sForm.Data(), kn);
925 fdst.ReplaceAll("<s0>", skn);
926 }
927 kn++;
928
929 // Replace user and group name
931 if (pw) {
932 if (fdst.Contains("<us>")) fdst.ReplaceAll("<us>", pw->fUser);
933 if (fdst.Contains("<gr>")) fdst.ReplaceAll("<gr>", pw->fGroup);
934 delete pw;
935 }
936 if (gProof && fdst.Contains("<pg>"))
937 fdst.ReplaceAll("<pg>", gProof->GetGroup());
938
939 // Now replace the subdirs, if required
940 if (dirph.GetSize() > 0)
941 TProofMgr::ReplaceSubdirs(gSystem->GetDirName(furl->GetFile()), fdst, dirph);
942
943 // Check double slashes in the file field (Turl sets things correctly inside)
944 TUrl u(fdst);
945 fdst = u.GetUrl();
946
947 // Copy the file now
948 ::Info("TProofMgr::UploadFiles", "uploading '%s' to '%s'", furl->GetUrl(), fdst.Data());
949 if (TFile::Cp(furl->GetUrl(), fdst.Data())) {
950 // Build TFileCollection
951 ds->Add(new TFileInfo(fdst.Data()));
952 } else {
953 ::Error("TProofMgr::UploadFiles", "file %s was not copied", furl->GetUrl());
954 }
955 }
956 }
957
958 // Return the TFileCollection
959 return ds;
960}
961
962////////////////////////////////////////////////////////////////////////////////
963/// Upload to 'mss' the files listed in the text file 'srcfiles' or contained
964/// in the directory 'srcfiles'.
965/// In the case 'srcfiles' is a text file, the files must be specified one per
966/// line, with line beginning by '#' ignored (i.e. considered comments).
967/// The path under 'mss' is defined by 'dest'; the following
968/// place-holders can be used in 'dest':
969/// <d0>, <d1>, <d2>, ... referring to the n-th sub-component
970/// of the src path
971/// <bn> basename in the source path
972/// <sn> serial number of file in the list
973/// <fn> the full file path
974/// <us>, <gr> the local user and group names.
975/// So, for example, if the source filename for the 99-th file is
976/// protosrc://host//d0/d1/d2/d3/d4/d5/myfile
977/// then with dest = '/pool/user/<d3>/<d4>/<d5>/<s>/<bn>' and
978/// mss = 'protodst://hostdst//nm/
979/// the corresponding destination path is
980/// protodst://hostdst//nm/pool/user/d3/d4/d5/99/myfile
981///
982/// If 'dest' is empty, <fn> is used.
983///
984/// Returns a TFileCollection with the destination files created; this
985/// TFileCollection is, for example, ready to be registered as dataset.
986
988 const char *mss, const char *dest)
989{
990 TFileCollection *ds = 0;
991
992 // The inputs must be make sense
993 if (!srcfiles || (srcfiles && strlen(srcfiles) <= 0)) {
994 ::Error("TProofMgr::UploadFiles", "input text file or directory undefined!");
995 return ds;
996 }
997 if (!mss || (mss && strlen(mss) <= 0)) {
998 ::Error("TProofMgr::UploadFiles", "MSS is undefined!");
999 return ds;
1000 }
1001
1002 TString inpath = srcfiles;
1003 gSystem->ExpandPathName(inpath);
1004
1005 FileStat_t fst;
1006 if (gSystem->GetPathInfo(inpath.Data(), fst)) {
1007 ::Error("TProofMgr::UploadFiles",
1008 "could not get information about the input path '%s':"
1009 " make sure that it exists and is readable", srcfiles);
1010 return ds;
1011 }
1012
1013 // Create the list to feed UploadFile(TList *, ...)
1014 TList files;
1015 files.SetOwner();
1016
1017 TString line;
1018 if (R_ISREG(fst.fMode)) {
1019 // Text file
1020 std::ifstream f;
1021 f.open(inpath.Data(), std::ifstream::out);
1022 if (f.is_open()) {
1023 while (f.good()) {
1024 line.ReadToDelim(f);
1025 line.Strip(TString::kTrailing, '\n');
1026 // Skip comments
1027 if (line.BeginsWith("#")) continue;
1029 files.Add(new TFileInfo(line));
1030 }
1031 f.close();
1032 } else {
1033 ::Error("TProofMgr::UploadFiles", "unable to open file '%s'", srcfiles);
1034 }
1035 } else if (R_ISDIR(fst.fMode)) {
1036 // Directory
1037 void *dirp = gSystem->OpenDirectory(inpath.Data());
1038 if (dirp) {
1039 const char *ent = 0;
1040 while ((ent = gSystem->GetDirEntry(dirp))) {
1041 if (!strcmp(ent, ".") || !strcmp(ent, "..")) continue;
1042 line.Form("%s/%s", inpath.Data(), ent);
1044 files.Add(new TFileInfo(line));
1045 }
1046 gSystem->FreeDirectory(dirp);
1047 } else {
1048 ::Error("TProofMgr::UploadFiles", "unable to open directory '%s'", inpath.Data());
1049 }
1050 } else {
1051 ::Error("TProofMgr::UploadFiles",
1052 "input path '%s' is neither a regular file nor a directory!", inpath.Data());
1053 return ds;
1054 }
1055 if (files.GetSize() <= 0) {
1056 ::Warning("TProofMgr::UploadFiles", "no files found in file or directory '%s'", inpath.Data());
1057 } else {
1058 ds = TProofMgr::UploadFiles(&files, mss, dest);
1059 }
1060 // Done
1061 return ds;
1062}
1063
1064////////////////////////////////////////////////////////////////////////////////
1065/// Run 'rm' on 'what'. Locally it is just a call to TSystem::Unlink .
1066
1067Int_t TProofMgr::Rm(const char *what, const char *, const char *)
1068{
1069 Int_t rc = -1;
1070 // Nothing to do if not in contact with proofserv
1071 if (!IsValid()) {
1072 Error("Rm", "invalid TProofMgr - do nothing");
1073 return rc;
1074 }
1075 // Nothing to do if not in contact with proofserv
1076 if (!what || (what && strlen(what) <= 0)) {
1077 Error("Rm", "path undefined!");
1078 return rc;
1079 }
1080
1081 TUrl u(what);
1082 if (!strcmp(u.GetProtocol(), "file")) {
1083 rc = gSystem->Unlink(u.GetFile());
1084 } else {
1085 rc = gSystem->Unlink(what);
1086 }
1087 // Done
1088 return (rc == 0) ? 0 : -1;
1089}
1090
1091//
1092// TProofDesc
1093//
1094
1096
1097////////////////////////////////////////////////////////////////////////////////
1098/// Dump the content to the screen.
1099
1101{
1102 const char *st[] = { "unknown", "idle", "processing", "shutting down"};
1103
1104 Printf("// # %d", fLocalId);
1105 Printf("// alias: %s, url: \"%s\"", GetTitle(), GetUrl());
1106 Printf("// tag: %s", GetName());
1107 Printf("// status: %s, attached: %s (remote ID: %d)",st[fStatus+1], (fProof ? "YES" : "NO"), fRemoteId);
1108}
UShort_t host2net(UShort_t x)
Definition: Bytes.h:564
UShort_t net2host(UShort_t x)
Definition: Bytes.h:577
void Class()
Definition: Class.C:29
#define SafeDelete(p)
Definition: RConfig.hxx:543
#define d(i)
Definition: RSha256.hxx:102
#define f(i)
Definition: RSha256.hxx:104
const Ssiz_t kNPOS
Definition: RtypesCore.h:113
int Int_t
Definition: RtypesCore.h:43
int Ssiz_t
Definition: RtypesCore.h:65
const Bool_t kFALSE
Definition: RtypesCore.h:90
bool Bool_t
Definition: RtypesCore.h:61
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
const Int_t kSysError
Definition: TError.h:41
void Error(const char *location, const char *msgfmt,...)
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:105
int type
Definition: TGX11.cxx:120
TProofMgr *(* TProofMgr_t)(const char *, Int_t, const char *)
Definition: TProofMgr.h:41
R__EXTERN TProof * gProof
Definition: TProof.h:1077
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:59
#define gROOT
Definition: TROOT.h:406
void Printf(const char *fmt,...)
@ kReadPermission
Definition: TSystem.h:46
Bool_t R_ISREG(Int_t mode)
Definition: TSystem.h:117
Bool_t R_ISDIR(Int_t mode)
Definition: TSystem.h:114
R__EXTERN TSystem * gSystem
Definition: TSystem.h:556
#define R__LOCKGUARD(mutex)
const char * proto
Definition: civetweb.c:16604
virtual Int_t GetEntries() const
Definition: TCollection.h:177
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.
Definition: TCollection.h:182
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
Class that contains a list of TFileInfo's and accumulated meta data information about its entries.
Int_t Add(TFileInfo *info)
Add TFileInfo to the collection.
Class describing a generic file including meta information.
Definition: TFileInfo.h:36
TUrl * GetFirstUrl() const
Definition: TFileInfo.h:69
virtual Bool_t Cp(const char *dst, Bool_t progressbar=kTRUE, UInt_t buffersize=1000000)
Allows to copy this file to the dst URL.
Definition: TFile.cxx:4839
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:821
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:577
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:356
virtual TObject * Last() const
Return the last object in the list. Returns 0 when list is empty.
Definition: TList.cxx:692
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:469
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Collectable string class.
Definition: TObjString.h:28
const char * GetName() const
Returns name of object.
Definition: TObjString.h:38
Mother of all ROOT objects.
Definition: TObject.h:37
void AbstractMethod(const char *method) const
Use this method to implement an "abstract" method that you don't want to leave purely abstract.
Definition: TObject.cxx:933
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:877
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:891
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:865
Named parameter, streamable and storable.
Definition: TParameter.h:37
Int_t fStatus
Definition: TProofMgr.h:151
Int_t fLocalId
Definition: TProofMgr.h:150
const char * GetUrl() const
Definition: TProofMgr.h:167
TProof * fProof
Definition: TProofMgr.h:152
Int_t fRemoteId
Definition: TProofMgr.h:153
void Print(Option_t *opt="") const
Dump the content to the screen.
Definition: TProofMgr.cxx:1100
Basic TProofMgr functionality implementation in the case of Lite session.
Definition: TProofMgrLite.h:27
The PROOF manager interacts with the PROOF server coordinator to create or destroy a PROOF session,...
Definition: TProofMgr.h:43
static TProofMgr_t GetXProofMgrHook()
Get the constructor hook fro TXProofMgr.
Definition: TProofMgr.cxx:596
virtual void ShowWorkers()
Show available workers.
Definition: TProofMgr.cxx:317
static void ReplaceSubdirs(const char *fn, TString &fdst, TList &dirph)
Parse file name extracting the directory subcomponents in dirs, stored as TObjStrings.
Definition: TProofMgr.cxx:745
virtual Int_t Reset(Bool_t hard=kFALSE, const char *usr=0)
Send a cleanup request for the sessions associated with the current user.
Definition: TProofMgr.cxx:307
virtual TList * QuerySessions(Option_t *opt="S")
Get list of sessions accessible to this manager.
Definition: TProofMgr.cxx:229
static TProofMgr * Create(const char *url, Int_t loglevel=-1, const char *alias=0, Bool_t xpd=kTRUE)
Static method returning the appropriate TProofMgr object using the plugin manager.
Definition: TProofMgr.cxx:499
virtual ~TProofMgr()
Destroy a TProofMgr instance.
Definition: TProofMgr.cxx:110
static TList * GetListOfManagers()
Extract pointers to PROOF managers from TROOT::fProofs.
Definition: TProofMgr.cxx:460
virtual Int_t SendMsgToUsers(const char *, const char *=0)
Send a message to connected users.
Definition: TProofMgr.cxx:295
virtual Int_t Rm(const char *, const char *=0, const char *=0)
Run 'rm' on 'what'. Locally it is just a call to TSystem::Unlink .
Definition: TProofMgr.cxx:1067
TSignalHandler * fIntHandler
Definition: TProofMgr.h:64
TUrl fUrl
Definition: TProofMgr.h:62
virtual TProof * CreateSession(const char *=0, const char *=0, Int_t=-1)
Create a new remote session (master and associated workers).
Definition: TProofMgr.cxx:387
static Int_t Ping(const char *url, Bool_t checkxrd=kFALSE)
Non-blocking check for a PROOF (or Xrootd, if checkxrd) service at 'url' Return 0 if a XProofd (or Xr...
Definition: TProofMgr.cxx:631
virtual Bool_t IsValid() const
Definition: TProofMgr.h:77
static TList fgListOfManagers
Definition: TProofMgr.h:66
static void SetTXProofMgrHook(TProofMgr_t pmh)
Set hook to TXProofMgr ctor.
Definition: TProofMgr.cxx:619
virtual void DetachSession(Int_t, Option_t *="")
Detach session with 'id' from its proofserv.
Definition: TProofMgr.cxx:160
virtual void SetAlias(const char *alias="")
Definition: TProofMgr.h:104
virtual TProof * AttachSession(Int_t, Bool_t=kFALSE)
Dummy version provided for completeness.
Definition: TProofMgr.cxx:124
virtual Bool_t IsProofd() const
Definition: TProofMgr.h:76
TProofMgr()
Definition: TProofMgr.h:68
virtual TProofDesc * GetProofDesc(Int_t id)
Get TProofDesc instance corresponding to 'id'.
Definition: TProofMgr.cxx:325
TList * fSessions
Definition: TProofMgr.h:61
static TProofMgr_t fgTXProofMgrHook
Definition: TProofMgr.h:52
virtual Bool_t MatchUrl(const char *url)
Checks if 'url' refers to the same 'user@host:port' entity as the URL in memory.
Definition: TProofMgr.cxx:431
virtual void DiscardSession(TProof *p)
Discard TProofDesc of session 'p' from the internal list.
Definition: TProofMgr.cxx:367
static TFileCollection * UploadFiles(TList *src, const char *mss, const char *dest=0)
Upload files provided via the list 'src' (as TFileInfo or TObjString) to 'mss'.
Definition: TProofMgr.cxx:802
EServType fServType
Definition: TProofMgr.h:60
This class controls a Parallel ROOT Facility, PROOF, cluster.
Definition: TProof.h:316
const char * GetSessionTag() const
Definition: TProof.h:909
Bool_t IsValid() const
Definition: TProof.h:937
Bool_t IsIdle() const
Definition: TProof.h:940
const char * GetUrl()
Definition: TProof.h:911
Int_t GetSessionID() const
Definition: TProof.h:919
const char * GetGroup() const
Definition: TProof.h:907
Regular expression class.
Definition: TRegexp.h:31
Basic string class.
Definition: TString.h:131
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1921
const char * Data() const
Definition: TString.h:364
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1763
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
@ kTrailing
Definition: TString.h:262
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:892
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
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:2311
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
virtual int GetServiceByName(const char *service)
Get port # of internet service.
Definition: TSystem.cxx:2319
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1269
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1002
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:841
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:832
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1850
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition: TSystem.cxx:1393
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:1291
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:849
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:930
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1027
virtual int Unlink(const char *name)
Unlink, i.e.
Definition: TSystem.cxx:1376
virtual UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
Definition: TSystem.cxx:1594
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:2013
This class represents a WWW compatible URL.
Definition: TUrl.h:35
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition: TUrl.cxx:387
const char * GetFile() const
Definition: TUrl.h:71
void SetUrl(const char *url, Bool_t defaultIsFile=kFALSE)
Parse url character string and split in its different subcomponents.
Definition: TUrl.cxx:108
void SetProtocol(const char *proto, Bool_t setDefaultPort=kFALSE)
Set protocol and, optionally, change the port accordingly.
Definition: TUrl.cxx:520
const char * GetUser() const
Definition: TUrl.h:67
const char * GetHost() const
Definition: TUrl.h:69
void SetOptions(const char *opt)
Definition: TUrl.h:89
const char * GetHostFQDN() const
Return fully qualified domain name of url host.
Definition: TUrl.cxx:469
void SetHost(const char *host)
Definition: TUrl.h:86
const char * GetProtocol() const
Definition: TUrl.h:66
void SetPort(Int_t port)
Definition: TUrl.h:90
Int_t GetPort() const
Definition: TUrl.h:80
TLine * line
Double_t ex[n]
Definition: legend1.C:17
static constexpr double nm
static constexpr double s
static constexpr double pi
static constexpr double ns
static constexpr double second
static constexpr double cm
Double_t Log10(Double_t x)
Definition: TMath.h:754
Definition: first.py:1
static const char * what
Definition: stlLoader.cc:6
Int_t fMode
Definition: TSystem.h:126
TString fUser
Definition: TSystem.h:140
TString fGroup
Definition: TSystem.h:141
auto * m
Definition: textangle.C:8
#define dest(otri, vertexptr)
Definition: triangle.c:1040