Belle II Software development
hlt-check-dqm-size.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9/* Basf2 headers. */
10#include <framework/logging/Logger.h>
11#include <framework/pcore/EvtMessage.h>
12#include <framework/pcore/MsgHandler.h>
13
14/* ROOT headers. */
15#include <TClass.h>
16#include <TCollection.h>
17#include <TDirectory.h>
18#include <TFile.h>
19#include <TH1.h>
20#include <TList.h>
21#include <TObject.h>
22#include <TKey.h>
23#include <TSystem.h>
24
25/* C++ headers. */
26#include <iostream>
27#include <memory>
28#include <string>
29#include <vector>
30
31/* LZ4 headers. */
32#include <lz4.h>
33
34/* ZeroMQ headers. */
35#include <zmq.hpp>
36
37namespace {
38
40 unsigned int streamHistograms(TDirectory* directory, Belle2::MsgHandler& msgHandler, const std::string& directoryName = "")
41 {
42 TList* keylist{directory->GetListOfKeys()};
43 TIter nextkey{keylist};
44 TKey* key{nullptr};
45 unsigned int counter{0};
46 while ((key = dynamic_cast<TKey*>(nextkey()))) {
47 TObject* object{directory->Get(key->GetName())};
48 TClass* objectClass{object->IsA()};
49 std::string objectName{directoryName};
50 if (not objectName.empty()) {
51 objectName += "/";
52 }
53 objectName += object->GetName();
54 if (objectClass->InheritsFrom(TH1::Class())) {
55 TH1* histogram{dynamic_cast<TH1*>(object)};
56 msgHandler.add(histogram, objectName);
57 counter++;
58 } else if (objectClass->InheritsFrom(TDirectory::Class())) {
59 TDirectory* subDirectory{dynamic_cast<TDirectory*>(object)};
60 // Apparently the dqm server does not understand multi-layer directory structures,
61 // therefore the original author broke this down to only show the last directory
62 counter += streamHistograms(subDirectory, msgHandler, object->GetName());
63 }
64 }
65 return counter;
66 }
67}
68
69int main(int argc, char* argv[])
70{
71 if (argc == 1 or std::string(argv[1]) == "--help" or std::string(argv[1]) == "-h") {
72 std::cout << "Usage: " << argv[0] << " INPUT_FILE\n\n"
73 " This tool checks if the online systems can handle the size of the DQM histograms\n"
74 " by compressing and decompressing them with LZ4 as done within our ZeroMQ framework.\n";
75 return 1;
76 }
77 std::string inputFileName{argv[1]};
78 if (inputFileName.find(".root") == std::string::npos) {
79 B2ERROR("The input file is not a .root file!");
80 return 1;
81 }
82 if (gSystem->AccessPathName(inputFileName.c_str())) {
83 B2ERROR("The input file does not exist!");
84 return 1;
85 }
86 std::unique_ptr<TFile> inputFile{
87 std::unique_ptr<TFile>(TFile::Open(inputFileName.c_str(), "READ"))
88 };
89 if (!inputFile or !inputFile->IsOpen() or inputFile->IsZombie()) {
90 B2ERROR("The input file is not working!");
91 return 1;
92 }
93 Belle2::MsgHandler msgHandler;
94 unsigned int streamedHistograms{streamHistograms(gDirectory, msgHandler)};
95 std::unique_ptr<Belle2::EvtMessage> evtMessage{
96 std::unique_ptr<Belle2::EvtMessage>(msgHandler.encode_msg(Belle2::ERecordType::MSG_EVENT))
97 };
98 size_t maximalCompressedSize{100000000};
99 std::vector<char> compressedBuffer;
100 compressedBuffer.resize(maximalCompressedSize, 0);
101 int compressedSize{
102 LZ4_compress_default(evtMessage->buffer(), &compressedBuffer[0],
103 evtMessage->size(), maximalCompressedSize)
104 };
105 if (compressedSize <= 0) {
106 B2ERROR("LZ4_compress_default failed"
107 << LogVar("file name", inputFileName)
108 << LogVar("streamed histograms", streamedHistograms)
109 << LogVar("original size", evtMessage->size())
110 << LogVar("compressed size", compressedSize));
111 inputFile->Close();
112 return 1;
113 }
114 zmq::message_t message{&compressedBuffer[0], static_cast<size_t>(compressedSize)};
115 size_t maximalUncompressedSize{128000000};
116 std::vector<char> uncompressedBuffer;
117 uncompressedBuffer.reserve(maximalUncompressedSize);
118 int uncompressedSize{
119 LZ4_decompress_safe(message.data<char>(), &uncompressedBuffer[0],
120 message.size(), maximalUncompressedSize)
121 };
122 if (uncompressedSize <= 0) {
123 B2ERROR("LZ4_decompress_safe failed"
124 << LogVar("file name", inputFileName)
125 << LogVar("streamed histograms", streamedHistograms)
126 << LogVar("original size", evtMessage->size())
127 << LogVar("compressed size", compressedSize)
128 << LogVar("uncompressed size", uncompressedSize));
129 inputFile->Close();
130 return 1;
131 }
132 if (evtMessage->size() != uncompressedSize) {
133 B2ERROR("Original size and decompressed size differ"
134 << LogVar("file name", inputFileName)
135 << LogVar("streamed histograms", streamedHistograms)
136 << LogVar("original size", evtMessage->size())
137 << LogVar("compressed size", compressedSize)
138 << LogVar("uncompressed size", uncompressedSize));
139 inputFile->Close();
140 return 1;
141 }
142 B2INFO("The compression/decompression cycle with LZ4 is successfully completed"
143 << LogVar("file name", inputFileName)
144 << LogVar("streamed histograms", streamedHistograms)
145 << LogVar("original size", evtMessage->size())
146 << LogVar("compressed size", compressedSize)
147 << LogVar("uncompressed size", uncompressedSize)
148 << LogVar("compressed/uncompressed ratio", (compressedSize * 1.) / uncompressedSize));
149 inputFile->Close();
150 return 0;
151}
A class to encode/decode an EvtMessage.
Definition: MsgHandler.h:103
virtual void add(const TObject *, const std::string &name)
Add an object to be streamed.
Definition: MsgHandler.cc:46
virtual EvtMessage * encode_msg(ERecordType rectype)
Stream object list into an EvtMessage.
Definition: MsgHandler.cc:67
Class to store variables with their name which were sent to the logging service.