2 #include "classlib/iobase/InetServerSocket.h" 3 #include "classlib/iobase/LocalServerSocket.h" 4 #include "classlib/iobase/Filename.h" 5 #include "classlib/sysapi/InetSocket.h" 6 #include "classlib/utils/TimeInfo.h" 7 #include "classlib/utils/StringList.h" 8 #include "classlib/utils/StringFormat.h" 9 #include "classlib/utils/StringOps.h" 10 #include "classlib/utils/SystemError.h" 11 #include "classlib/utils/Regexp.h" 26 #define MESSAGE_SIZE_LIMIT (1 * 1024 * 1024) 27 #define SOCKET_BUF_SIZE (1 * 1024 * 1024) 29 #define MESSAGE_SIZE_LIMIT (8 * 1024 * 1024) 30 #define SOCKET_BUF_SIZE (8 * 1024 * 1024) 32 #define SOCKET_READ_SIZE (SOCKET_BUF_SIZE / 8) 33 #define SOCKET_READ_GROWTH (SOCKET_BUF_SIZE) 37 static const Regexp
s_rxmeval(
"<(.*)>(i|f|s|qr)=(.*)</\\1>");
52 return std::cout <<
now.format(
true,
"%Y-%m-%d %H:%M:%S.") <<
now.nanoformat(3, 3) <<
" " << appname_ <<
"[" << pid_
58 b->data.insert(
b->data.end(), (
const unsigned char *)
data, (
const unsigned char *)
data + len);
80 for (
auto i = waiting_.begin(),
e = waiting_.end();
i !=
e;)
106 (*msg)->
next =
nullptr;
109 words[0] =
sizeof(words) + len;
110 words[1] = DQM_MSG_GET_OBJECT;
112 copydata(*
msg, words,
sizeof(words));
124 requestObjectData(owner, !
name.empty() ? &
name[0] :
nullptr,
name.size());
126 waiting_.push_back(wo);
137 (*msg)->
next =
nullptr;
139 releaseFromWait(*
msg, *
i,
o);
148 for (
auto i = waiting_.begin(),
e = waiting_.end();
i !=
e;)
150 releaseFromWait(
i++,
o);
160 std::ostringstream qrs;
161 QReports::const_iterator qi, qe;
162 for (qi = qr.begin(), qe = qr.end(); qi != qe; ++qi) {
164 sprintf(
buf,
"%d%c%n%.*g", qi->code, 0, &
pos, DBL_DIG + 2, qi->qtresult);
165 qrs <<
buf <<
'\0' <<
buf +
pos <<
'\0' << qi->qtname <<
'\0' << qi->algorithm <<
'\0' << qi->message <<
'\0' 174 const char *qdata = from;
204 qv.
code = atoi(qdata);
245 if (
buf.Length() ==
buf.BufferSize())
250 TClass *
c =
buf.ReadClass();
253 return c ?
buf.ReadObject(
c) : 0;
258 DQMNet::reconstructObject(Object &
o)
260 TBufferFile
buf(TBufferFile::kRead,
o.rawdata.size(), &
o.rawdata[0], kFALSE);
271 unpackQualityData(
o.qreports,
o.flags,
o.qdata.c_str());
278 DQMNet::reinstateObject(
DQMStore *store, Object &
o)
280 if (! reconstructObject (
o))
286 switch (
o.flags & DQM_PROP_TYPE_MASK)
288 case DQM_PROP_TYPE_INT:
290 obj->Fill(atoll(
o.scalar.c_str()));
293 case DQM_PROP_TYPE_REAL:
295 obj->Fill(atof(
o.scalar.c_str()));
298 case DQM_PROP_TYPE_STRING:
302 case DQM_PROP_TYPE_TH1F:
306 case DQM_PROP_TYPE_TH1S:
310 case DQM_PROP_TYPE_TH1D:
314 case DQM_PROP_TYPE_TH1I:
318 case DQM_PROP_TYPE_TH2F:
322 case DQM_PROP_TYPE_TH2S:
326 case DQM_PROP_TYPE_TH2D:
330 case DQM_PROP_TYPE_TH2I:
334 case DQM_PROP_TYPE_TH3F:
338 case DQM_PROP_TYPE_TH3S:
339 obj = store->book3S(
name, dynamic_cast<TH3S *>(
o.object));
342 case DQM_PROP_TYPE_TH3D:
343 obj = store->book3DD(
name, dynamic_cast<TH3D *>(
o.object));
346 case DQM_PROP_TYPE_PROF:
350 case DQM_PROP_TYPE_PROF2D:
356 <<
"ERROR: unexpected monitor element of type " 357 << (
o.flags & DQM_PROP_TYPE_MASK) <<
" called '" 358 <<
o.dirname <<
'/' <<
o.objname <<
"'\n";
365 obj->data_.tag =
o.tag;
366 obj->data_.qreports =
o.qreports;
382 sendObjectToPeer(
msg, *
o,
true);
385 words[0] =
sizeof(words) +
w.name.size();
386 words[1] = DQM_REPLY_NONE;
387 words[2] =
w.name.size();
389 msg->data.reserve(
msg->data.size() + words[0]);
390 copydata(
msg, &words[0],
sizeof(words));
391 copydata(
msg, &
w.name[0],
w.name.size());
399 uint32_t
flags =
o.flags & ~DQM_PROP_DEAD;
402 if ((
flags & DQM_PROP_TYPE_MASK) <= DQM_PROP_TYPE_SCALAR)
403 objdata.insert(objdata.end(), &
o.scalar[0], &
o.scalar[0] +
o.scalar.size());
405 objdata.insert(objdata.end(), &
o.rawdata[0], &
o.rawdata[0] +
o.rawdata.size());
408 uint32_t namelen =
o.dirname.size() +
o.objname.size() + 1;
409 uint32_t datalen = objdata.size();
410 uint32_t qlen =
o.qdata.size();
412 if (
o.dirname.empty())
415 words[0] = 9 *
sizeof(uint32_t) + namelen + datalen + qlen;
416 words[1] = DQM_REPLY_OBJECT;
418 words[3] = (
o.version >> 0) & 0xffffffff;
419 words[4] = (
o.version >> 32) & 0xffffffff;
425 msg->data.reserve(
msg->data.size() + words[0]);
426 copydata(
msg, &words[0], 9 *
sizeof(uint32_t));
428 copydata(
msg, &(
o.dirname)[0],
o.dirname.size());
429 if (!
o.dirname.empty())
430 copydata(
msg,
"/", 1);
431 copydata(
msg, &
o.objname[0],
o.objname.size());
434 copydata(
msg, &objdata[0], datalen);
436 copydata(
msg, &
o.qdata[0], qlen);
446 case DQM_MSG_UPDATE_ME: {
447 if (len != 2 *
sizeof(uint32_t)) {
448 logme() <<
"ERROR: corrupt 'UPDATE_ME' message of length " << len <<
" from peer " <<
p->peeraddr << std::endl;
453 logme() <<
"DEBUG: received message 'UPDATE ME' from peer " <<
p->peeraddr <<
", size " << len << std::endl;
459 case DQM_MSG_LIST_OBJECTS: {
461 logme() <<
"DEBUG: received message 'LIST OBJECTS' from peer " <<
p->peeraddr <<
", size " << len << std::endl;
464 sendObjectListToPeer(
msg,
true,
false);
468 case DQM_MSG_GET_OBJECT: {
470 logme() <<
"DEBUG: received message 'GET OBJECT' from peer " <<
p->peeraddr <<
", size " << len << std::endl;
472 if (len < 3 *
sizeof(uint32_t)) {
473 logme() <<
"ERROR: corrupt 'GET IMAGE' message of length " << len <<
" from peer " <<
p->peeraddr << std::endl;
478 memcpy(&namelen,
data + 2 *
sizeof(uint32_t),
sizeof(namelen));
479 if (len != 3 *
sizeof(uint32_t) + namelen) {
480 logme() <<
"ERROR: corrupt 'GET OBJECT' message of length " << len <<
" from peer " <<
p->peeraddr
481 <<
", expected length " << (3 *
sizeof(uint32_t)) <<
" + " << namelen << std::endl;
486 Peer *owner =
nullptr;
489 o->lastreq = Time::current().ns();
490 if ((
o->rawdata.empty() || (
o->flags & DQM_PROP_STALE)) &&
491 (
o->flags & DQM_PROP_TYPE_MASK) > DQM_PROP_TYPE_SCALAR)
492 waitForData(
p,
name,
"", owner);
494 sendObjectToPeer(
msg, *
o,
true);
497 words[0] =
sizeof(words) +
name.size();
498 words[1] = DQM_REPLY_NONE;
499 words[2] =
name.size();
501 msg->data.reserve(
msg->data.size() + words[0]);
502 copydata(
msg, &words[0],
sizeof(words));
508 case DQM_REPLY_LIST_BEGIN: {
509 if (len != 4 *
sizeof(uint32_t)) {
510 logme() <<
"ERROR: corrupt 'LIST BEGIN' message of length " << len <<
" from peer " <<
p->peeraddr << std::endl;
516 memcpy(&
flags,
data + 3 *
sizeof(uint32_t),
sizeof(uint32_t));
519 logme() <<
"DEBUG: received message 'LIST BEGIN " << (
flags ?
"FULL" :
"INCREMENTAL") <<
"' from " 520 <<
p->peeraddr <<
", size " << len << std::endl;
533 case DQM_REPLY_LIST_END: {
534 if (len != 4 *
sizeof(uint32_t)) {
535 logme() <<
"ERROR: corrupt 'LIST END' message of length " << len <<
" from peer " <<
p->peeraddr << std::endl;
541 memcpy(&
flags,
data + 3 *
sizeof(uint32_t),
sizeof(uint32_t));
551 logme() <<
"DEBUG: received message 'LIST END " << (
flags ?
"FULL" :
"INCREMENTAL") <<
"' from " <<
p->peeraddr
552 <<
", size " << len << std::endl;
561 case DQM_REPLY_OBJECT: {
563 if (len <
sizeof(words)) {
564 logme() <<
"ERROR: corrupt 'OBJECT' message of length " << len <<
" from peer " <<
p->peeraddr << std::endl;
568 memcpy(&words[0],
data,
sizeof(words));
569 uint32_t &namelen = words[6];
570 uint32_t &datalen = words[7];
571 uint32_t &qlen = words[8];
573 if (len !=
sizeof(words) + namelen + datalen + qlen) {
574 logme() <<
"ERROR: corrupt 'OBJECT' message of length " << len <<
" from peer " <<
p->peeraddr
575 <<
", expected length " <<
sizeof(words) <<
" + " << namelen <<
" + " << datalen <<
" + " << qlen
580 unsigned char *namedata =
data +
sizeof(words);
581 unsigned char *objdata = namedata + namelen;
582 unsigned char *qdata = objdata + datalen;
583 unsigned char *enddata = qdata + qlen;
588 logme() <<
"DEBUG: received message 'OBJECT " <<
name <<
"' from " <<
p->peeraddr <<
", size " << len
599 o->flags = words[2] | DQM_PROP_NEW | DQM_PROP_RECEIVED;
601 o->version = ((
uint64_t)words[4] << 32 | words[3]);
604 if ((
o->flags & DQM_PROP_TYPE_MASK) <= DQM_PROP_TYPE_SCALAR) {
606 o->scalar.insert(
o->scalar.end(), objdata, qdata);
607 }
else if (datalen) {
609 o->rawdata.insert(
o->rawdata.end(), objdata, qdata);
610 }
else if (!
o->rawdata.empty())
611 o->flags |= DQM_PROP_STALE;
612 o->qdata.insert(
o->qdata.end(), qdata, enddata);
616 if (
o->lastreq && !datalen && (
o->flags & DQM_PROP_TYPE_MASK) > DQM_PROP_TYPE_SCALAR)
617 requestObjectData(
p, (namelen ? &
name[0] :
nullptr), namelen);
621 releaseWaiters(
name,
o);
625 case DQM_REPLY_NONE: {
627 if (len <
sizeof(words)) {
628 logme() <<
"ERROR: corrupt 'NONE' message of length " << len <<
" from peer " <<
p->peeraddr << std::endl;
632 memcpy(&words[0],
data,
sizeof(words));
633 uint32_t &namelen = words[2];
635 if (len !=
sizeof(words) + namelen) {
636 logme() <<
"ERROR: corrupt 'NONE' message of length " << len <<
" from peer " <<
p->peeraddr
637 <<
", expected length " <<
sizeof(words) <<
" + " << namelen << std::endl;
641 unsigned char *namedata =
data +
sizeof(words);
645 logme() <<
"DEBUG: received message 'NONE " <<
name <<
"' from " <<
p->peeraddr <<
", size " << len
653 o->flags |= DQM_PROP_DEAD;
658 releaseWaiters(
name,
nullptr);
663 logme() <<
"ERROR: unrecognised message of length " << len <<
" and type " <<
type <<
" from peer " <<
p->peeraddr
673 assert(getPeer(dynamic_cast<Socket *>(
ev->source)) ==
p);
681 logme() <<
"WARNING: connection to the DQM server at " <<
p->peeraddr
682 <<
" lost (will attempt to reconnect in 15 seconds)\n";
683 losePeer(
nullptr,
p,
ev);
685 losePeer(
"WARNING: lost peer connection ",
p,
ev);
694 IOSize len =
b->data.size() -
p->sendpos;
695 const void *
data = (len ? (
const void *)&
b->data[
p->sendpos] : (
const void *)&
data);
699 done = (len ?
ev->source->write(
data, len) : 0);
701 logme() <<
"DEBUG: sent " <<
done <<
" bytes to peer " <<
p->peeraddr << std::endl;
703 losePeer(
"WARNING: unable to write to peer ",
p,
ev, &
e);
709 if (
p->sendpos ==
b->data.size()) {
711 p->sendq = old->
next;
733 if ((sz =
ev->source->read(&
buf[0],
buf.size()))) {
735 logme() <<
"DEBUG: received " << sz <<
" bytes from peer " <<
p->peeraddr << std::endl;
737 if (
data.capacity() <
data.size() + sz)
741 while (sz ==
sizeof(
buf));
743 auto *
next =
dynamic_cast<SystemError *
>(
e.next());
744 if (
next &&
next->portable() == SysErr::ErrTryAgain)
748 losePeer(
"WARNING: failed to read from peer ",
p,
ev, &
e);
757 while (
data.size() - consumed >=
sizeof(uint32_t) &&
p->waiting < MAX_PEER_WAITREQS) {
759 memcpy(&msglen, &
data[0] + consumed,
sizeof(msglen));
762 losePeer(
"WARNING: excessively large message from ",
p,
ev);
767 if (
data.size() - consumed >= msglen) {
769 if (msglen < 2 *
sizeof(uint32_t)) {
770 logme() <<
"ERROR: corrupt peer message of length " << msglen <<
" from peer " <<
p->peeraddr << std::endl;
779 if (!
msg.data.empty()) {
782 prev = &(*prev)->
next;
785 (*prev)->
next =
nullptr;
791 losePeer(
"WARNING: data stream error with ",
p,
ev);
807 sel_.setMask(
p->socket,
p->mask &= ~
IORead);
824 Socket *
s = server_->accept();
832 if (
auto *inet = dynamic_cast<InetSocket *>(
s)) {
833 InetAddress peeraddr = inet->peername();
834 InetAddress myaddr = inet->sockname();
835 p->peeraddr = StringFormat(
"%1:%2").arg(peeraddr.hostname()).
arg(peeraddr.port()).
value();
836 localaddr = StringFormat(
"%1:%2").arg(myaddr.hostname()).
arg(myaddr.port()).
value();
837 }
else if (
auto *
local = dynamic_cast<LocalSocket *>(
s)) {
838 p->peeraddr =
local->peername().path();
839 localaddr =
local->sockname().path();
848 logme() <<
"INFO: new peer " <<
p->peeraddr <<
" is now connected to " << localaddr << std::endl;
868 unsigned char buf[1024];
869 while ((sz =
ev->source->read(
buf,
sizeof(
buf))))
872 auto *
next =
dynamic_cast<SystemError *
>(
e.next());
873 if (
next &&
next->portable() == SysErr::ErrTryAgain)
876 logme() <<
"WARNING: error reading from notification pipe: " <<
e.explain() << std::endl;
893 unsigned oldmask =
p->mask;
895 sel_.setMask(
p->socket,
p->mask &= ~
IOWrite);
898 sel_.setMask(
p->socket,
p->mask |=
IOWrite);
900 if (debug_ && oldmask !=
p->mask)
901 logme() <<
"DEBUG: updating mask for " <<
p->peeraddr <<
" to " <<
p->mask <<
" from " << oldmask << std::endl;
908 logme() <<
"INFO: connection closed to " <<
p->peeraddr << std::endl;
909 losePeer(
nullptr,
p,
nullptr);
916 appname_(appname.
empty() ?
"DQMNet" : appname.c_str()),
919 version_(
Time::current()),
920 communicate_((pthread_t)-1),
923 waitStale_(0, 0, 0, 0, 500000000 ),
924 waitMax_(0, 0, 0, 5 , 0),
962 logme() <<
"ERROR: DQM server was already started.\n";
968 auto *
s =
new InetSocket(SOCK_STREAM, 0,
addr.family());
973 s->setBlocking(
false);
978 logme() <<
"ERROR: Failed to start server at port " <<
port <<
": " <<
e.explain() << std::endl;
980 throw cms::Exception(
"DQMNet::startLocalServer") <<
"Failed to start server at port " <<
982 port <<
": " <<
e.explain().c_str();
985 logme() <<
"INFO: DQM server started at port " <<
port << std::endl;
993 logme() <<
"ERROR: DQM server was already started.\n";
1006 logme() <<
"ERROR: Failed to start server at path " <<
path <<
": " <<
e.explain() << std::endl;
1009 <<
"Failed to start server at path " <<
path <<
": " <<
e.explain().c_str();
1012 logme() <<
"INFO: DQM server started at path " <<
path << std::endl;
1060 pthread_sigmask(SIG_BLOCK, &sigs,
nullptr);
1068 pthread_mutex_lock(&
lock_);
1074 pthread_mutex_unlock(&
lock_);
1082 logme() <<
"ERROR: DQM networking thread has already been started\n";
1086 pthread_mutex_init(&
lock_,
nullptr);
1098 for (
auto ap : automatic) {
1102 if (!ap->host.empty() && !ap->peer && (
now = Time::current()) > ap->next) {
1103 ap->
next =
now + TimeSpan(0, 0, 0, 15 , 0);
1104 InetSocket *
s =
nullptr;
1106 InetAddress
addr(ap->host.c_str(), ap->port);
1107 s =
new InetSocket(SOCK_STREAM, 0,
addr.family());
1108 s->setBlocking(
false);
1113 auto *sys =
dynamic_cast<SystemError *
>(
e.next());
1114 if (!sys || sys->portable() != SysErr::ErrOperationInProgress) {
1131 InetAddress peeraddr = ((InetSocket *)
s)->peername();
1132 InetAddress myaddr = ((InetSocket *)
s)->sockname();
1133 p->peeraddr = StringFormat(
"%1:%2").arg(peeraddr.hostname()).
arg(peeraddr.port()).
value();
1135 p->update = ap->update;
1142 p->sendq->next =
nullptr;
1143 copydata(
p->sendq, words,
sizeof(words));
1148 logme() <<
"INFO: now connected to " <<
p->peeraddr <<
" from " << myaddr.hostname() <<
":" << myaddr.port()
1156 now = Time::current();
1163 nextFlush =
now + TimeSpan(0, 0, 0, 15 , 0);
1182 if (
i->time < waitold) {
1183 logme() <<
"WARNING: source not responding in " << (
waitMax_.ns() * 1
e-9) <<
"s to retrieval, releasing '" 1184 <<
i->name <<
"' from wait, have " << (
o ?
o->rawdata.size() : 0) <<
" data available\n";
1187 logme() <<
"WARNING: source not responding in " << (
waitStale_.ns() * 1
e-9) <<
"s to update, releasing '" 1188 <<
i->name <<
"' from wait, have " <<
o->rawdata.size() <<
" data available\n";
1205 wakeup_.sink()->write(&byte, 1);
1221 o.dirname = *
local_->dirs.insert(
o.dirname).first;
1222 std::pair<ObjectMap::iterator, bool>
info(
local_->objs.insert(
o));
1227 auto &old =
const_cast<Object &
>(*
info.first);
1244 ObjectMap::iterator
i,
e;
1247 path.reserve(
i->dirname.size() +
i->objname.size() + 2);
1253 if (!known.count(
path))
1254 ++removed,
local_->objs.erase(
i++);
edm::ErrorSummaryEntry Error
static void unpackQualityData(QReports &qr, uint32_t &flags, const char *from)
DQMNet(const std::string &appname="")
static const uint32_t DQM_PROP_REPORT_WARN
static const uint32_t DQM_MSG_UPDATE_ME
MonitorElement * bookFloat(TString const &name, FUNC onbooking=NOOP())
bool onLocalNotify(lat::IOSelectEvent *ev)
MonitorElement * bookProfile2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, double lowZ, double highZ, char const *option="s", FUNC onbooking=NOOP())
MonitorElement * book1I(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
MonitorElement * book2S(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
virtual void sendObjectListToPeers(bool all)=0
void lock()
Acquire a lock on the DQM net layer.
static const Regexp s_rxmeval("<(.*)>(i|f|s|qr)=(.*)</>")
#define MESSAGE_SIZE_LIMIT
TObject * extractNextObject(TBufferFile &buf)
static void discard(Bucket *&b)
virtual void updatePeerMasks()=0
virtual Peer * createPeer(lat::Socket *s)=0
void setCurrentFolder(std::string const &fullpath) override
void releaseWaiters(const std::string &name, Object *o)
void staleObjectWaitLimit(lat::TimeSpan time)
static void * communicate(void *obj)
void shutdown()
Stop the network layer and wait it to finish.
void swap(Association< C > &lhs, Association< C > &rhs)
MonitorElement * bookString(TString const &name, TString const &value, FUNC onbooking=NOOP())
MonitorElement * book1DD(TString const &name, TString const &title, int nchX, double lowX, double highX, FUNC onbooking=NOOP())
void waitForData(Peer *p, const std::string &name, const std::string &info, Peer *owner)
virtual bool shouldStop()
void requestObjectData(Peer *p, const char *name, size_t len)
Queue an object request to the data server.
MonitorElement * bookProfile(TString const &name, TString const &title, int nchX, double lowX, double highX, int, double lowY, double highY, char const *option="s", FUNC onbooking=NOOP())
virtual Object * findObject(Peer *p, const std::string &name, Peer **owner=nullptr)=0
virtual bool onMessage(Bucket *msg, Peer *p, unsigned char *data, size_t len)
bool onPeerData(lat::IOSelectEvent *ev, Peer *p)
Handle communication to a particular client.
MonitorElement * book1S(TString const &name, TString const &title, int nchX, double lowX, double highX, FUNC onbooking=NOOP())
static const uint32_t DQM_PROP_REPORT_ERROR
#define SOCKET_READ_GROWTH
static const uint32_t DQM_PROP_REPORT_OTHER
virtual void releaseFromWait(Bucket *msg, WaitObject &w, Object *o)
Peer * createPeer(lat::Socket *s) override
virtual void sendObjectToPeer(Bucket *msg, Object &o, bool data)
unsigned long long uint64_t
bool removeLocalExcept(const std::set< std::string > &known)
bool onPeerConnect(lat::IOSelectEvent *ev)
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
MonitorElement * bookInt(TString const &name, FUNC onbooking=NOOP())
void startLocalServer(int port)
static void packQualityData(std::string &into, const QReports &qr)
static const uint32_t DQM_PROP_STALE
MonitorElement * book2DD(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
void losePeer(const char *reason, Peer *peer, lat::IOSelectEvent *event, lat::Error *err=nullptr)
char data[epos_bytes_allocation]
void unlock()
Release the lock on the DQM net layer.
void listenToCollector(const std::string &host, int port)
static const int STATUS_OK
static const uint32_t DQM_MSG_LIST_OBJECTS
static void copydata(Bucket *b, const void *data, size_t len)
void updateLocalObject(Object &o)
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
std::vector< QValue > QReports
void reserveLocalSpace(uint32_t size)
Give a hint of how much capacity to allocate for local objects.
MonitorElement * book3D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, int nchZ, double lowZ, double highZ, FUNC onbooking=NOOP())
MonitorElement * book2I(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
void updateToCollector(const std::string &host, int port)
std::vector< unsigned char > DataBlob
DQMBasicNet(const std::string &appname="")