Project

General

Profile

TFileService_service.cc

Kyle Knoepfel, 11/02/2017 09:06 AM

 
1
// ======================================================================
2
//
3
// TFileService
4
//
5
// ======================================================================
6

    
7
#include "art/Framework/Services/Optional/TFileService.h"
8

    
9
#include "art/Framework/IO/PostCloseFileRenamer.h"
10
#include "art/Framework/IO/Root/detail/rootOutputConfigurationTools.h"
11
#include "art/Framework/IO/detail/logFileAction.h"
12
#include "art/Framework/Principal/Event.h"
13
#include "art/Framework/Principal/Run.h"
14
#include "art/Framework/Principal/SubRun.h"
15
#include "art/Framework/Services/Registry/ActivityRegistry.h"
16
#include "art/Framework/Services/Registry/ServiceHandle.h"
17
#include "art/Framework/Services/System/TriggerNamesService.h"
18
#include "art/Utilities/parent_path.h"
19
#include "art/Utilities/unique_filename.h"
20
#include "canvas/Persistency/Provenance/ModuleDescription.h"
21
#include "cetlib/assert_only_one_thread.h"
22
#include "fhiclcpp/ParameterSet.h"
23

    
24
#include "TFile.h"
25
#include "TROOT.h"
26

    
27
using namespace std;
28
using art::TFileService;
29
using fhicl::ParameterSet;
30

    
31
// ----------------------------------------------------------------------
32

    
33
TFileService::TFileService(ServiceTable<Config> const& config,
34
                           ActivityRegistry& r)
35
  : TFileDirectory{"", "", nullptr, ""}
36
  , closeFileFast_{config().closeFileFast()}
37
  , fstats_{config.get_PSet().get<std::string>("service_type"), ServiceHandle<TriggerNamesService const>{}->getProcessName()}
38
  , filePattern_{config().fileName()}
39
  , tmpDir_{config().tmpDir()}
40
{
41
  ClosingCriteria::Config fpConfig;
42
  requireCallback_ = config().fileProperties(fpConfig);
43
  if (requireCallback_) {
44
    detail::validateFileNamePattern(requireCallback_, filePattern_);
45
    fileSwitchCriteria_ = ClosingCriteria{fpConfig};
46
  }
47
  openFile_();
48

    
49
  // Activities to monitor in order to set the proper directory.
50
  r.sPostOpenFile.watch([this](std::string const& fileName) { fstats_.recordInputFile(fileName); });
51

    
52
  r.sPreModuleBeginJob.watch(this, &TFileService::setDirectoryName_);
53
  r.sPreModuleEndJob.watch(this, &TFileService::setDirectoryName_);
54

    
55
  r.sPreModuleConstruction.watch(this, &TFileService::setDirectoryName_);
56
  r.sPreModuleRespondToOpenInputFile.watch(this,
57
                                           &TFileService::setDirectoryName_);
58
  r.sPreModuleRespondToCloseInputFile.watch(this,
59
                                            &TFileService::setDirectoryName_);
60
  r.sPreModuleRespondToOpenOutputFiles.watch(this,
61
                                             &TFileService::setDirectoryName_);
62
  r.sPreModuleRespondToCloseOutputFiles.watch(this,
63
                                              &TFileService::setDirectoryName_);
64

    
65
  r.sPreModuleBeginRun.watch(this, &TFileService::setDirectoryName_);
66
  r.sPreModuleEndRun.watch(this, &TFileService::setDirectoryName_);
67

    
68
  r.sPreModuleBeginSubRun.watch(this, &TFileService::setDirectoryName_);
69
  r.sPreModuleEndSubRun.watch(this, &TFileService::setDirectoryName_);
70

    
71
  r.sPreModule.watch(this, &TFileService::setDirectoryName_);
72

    
73
  // Activities to monitor to keep track of events, subruns and runs seen.
74
  r.sPostProcessEvent.watch(
75
    [this](Event const& e) {
76
      currentGranularity_ = Granularity::Event;
77
      fp_.update<Granularity::Event>(status_);
78
      fstats_.recordEvent(e.id());
79
      if (requestsToCloseFile_()) {
80
        maybeSwitchFiles_();
81
      }
82
    });
83
  r.sPostEndSubRun.watch(
84
    [this](SubRun const& sr) {
85
      currentGranularity_ = Granularity::SubRun;
86
      fp_.update<Granularity::SubRun>(status_);
87
      fstats_.recordSubRun(sr.id());
88
      if (requestsToCloseFile_()) {
89
        maybeSwitchFiles_();
90
      }
91
    });
92
  r.sPostEndRun.watch([this](Run const& r) {
93
      currentGranularity_ = Granularity::Run;
94
      fp_.update<Granularity::Run>(status_);
95
      fstats_.recordRun(r.id());
96
      if (requestsToCloseFile_()) {
97
        maybeSwitchFiles_();
98
      }
99
    });
100
  r.sPostCloseFile.watch([this]{
101
      currentGranularity_ = Granularity::InputFile;
102
      fp_.update<Granularity::InputFile>();
103
      if (requestsToCloseFile_()) {
104
        maybeSwitchFiles_();
105
      }
106
    });
107
}
108

    
109

    
110
TFileService::~TFileService()
111
{
112
  closeFile_();
113
}
114

    
115
void
116
TFileService::registerFileSwitchCallback(Callback_t cb)
117
{
118
  registerCallback(cb);
119
}
120

    
121
void
122
TFileService::setDirectoryName_(ModuleDescription const& desc)
123
{
124
  CET_ASSERT_ONLY_ONE_THREAD();
125
  dir_ = desc.moduleLabel();
126
  descr_ = dir_ ;
127
  descr_ += " (";
128
  descr_ += desc.moduleName();
129
  descr_ += ") folder";
130
}
131

    
132
void
133
TFileService::openFile_()
134
{
135
  uniqueFilename_ = unique_filename((tmpDir_ == default_tmpDir ?
136
                                     parent_path(filePattern_) :
137
                                     tmpDir_) +
138
                                    "/TFileService");
139
  assert(file_ == nullptr && "TFile pointer should always be zero here!");
140
  beginTime_ = std::chrono::steady_clock::now();
141
  file_ = new TFile{uniqueFilename_.c_str(), "RECREATE"};
142
  status_ = OutputFileStatus::Open;
143
  fstats_.recordFileOpen();
144
}
145

    
146
void
147
TFileService::closeFile_()
148
{
149
  file_->Write();
150
  if (closeFileFast_) {
151
    gROOT->GetListOfFiles()->Remove(file_);
152
  }
153
  file_->Close();
154
  delete file_;
155
  file_ = nullptr;
156
  status_ = OutputFileStatus::Closed;
157
  fstats_.recordFileClose();
158
  lastClosedFile_ = PostCloseFileRenamer{fstats_}.maybeRenameFile(uniqueFilename_, filePattern_);
159
}
160

    
161
void
162
TFileService::maybeSwitchFiles_()
163
{
164
  // FIXME: Should maybe include the granularity check in
165
  // requestsToCloseFile_().
166
  if (fileSwitchCriteria_.granularity() > currentGranularity_) return;
167

    
168
  status_ = OutputFileStatus::Switching;
169
  closeFile_();
170
  detail::logFileAction("Closed TFileService file ", lastClosedFile_);
171
  detail::logFileAction("Switching to new TFileService file with pattern ", filePattern_);
172
  fp_ = FileProperties{};
173
  openFile_();
174
  invokeCallbacks();
175
}
176

    
177
bool
178
TFileService::requestsToCloseFile_()
179
{
180
  using namespace std::chrono;
181
  unsigned int constexpr oneK{1024u};
182
  fp_.updateSize(file_->GetSize() / oneK);
183
  fp_.updateAge(duration_cast<seconds>(steady_clock::now() - beginTime_));
184
  return fileSwitchCriteria_.should_close(fp_);
185
}
186

    
187
DEFINE_ART_SERVICE(TFileService)