ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
PhysicsAnalysis
D3PDTools
SampleHandler
Root
DiskWriterXRD.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3
*/
4
6
7
8
//
9
// includes
10
//
11
12
#include <
SampleHandler/DiskWriterXRD.h
>
13
14
#include <
RootCoreUtils/Assert.h
>
15
#include <
RootCoreUtils/ShellExec.h
>
16
#include <TFile.h>
17
#include <TSystem.h>
18
#include <format>
19
#include <boost/functional/hash.hpp>
20
#include <chrono>
21
#include <iostream>
22
#include <optional>
23
#include <random>
24
#include <sstream>
25
#include <stdexcept>
26
#include <sys/types.h>
27
#include <thread>
28
#include <unistd.h>
29
30
//
31
// method implementations
32
//
33
34
namespace
SH
35
{
36
void
DiskWriterXRD ::
37
testInvariant ()
const
38
{
39
}
40
41
42
43
DiskWriterXRD ::
44
DiskWriterXRD (
const
std::string& val_path)
45
:
m_path
(val_path)
46
{
47
RCU_REQUIRE
(val_path.find (
"root://"
) == 0);
48
49
const
char
*tmpdir = getenv (
"TMPDIR"
);
50
std::size_t hash {0};
51
boost::hash_combine (hash, std::hash<pid_t>() (getpid()));
52
std::size_t tries = 0;
53
while
(
m_file
==
nullptr
|| !
m_file
->IsOpen())
54
{
55
if
(++ tries == 10)
56
throw
std::runtime_error (
"infinite loop trying to create tempory file for DiskWriterXRD"
);
57
58
auto
time = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
59
boost::hash_combine (hash, std::hash<
decltype
(time)>() (time));
60
std::size_t hash16 {hash};
61
while
(hash16 > 0xffff)
62
hash16 = (hash16&0xffff) ^ (hash16 >> 16);
63
64
std::ostringstream
str
;
65
if
(tmpdir)
66
str
<< tmpdir;
67
else
68
str
<<
"/tmp"
;
69
str
<<
"/SH-XRD-"
<<
m_path
.substr (
m_path
.rfind (
"/"
)+1)
70
<<
"-"
<< std::format(
"{:04x}"
, hash16);
71
m_tmp
=
str
.str();
72
if
(gSystem->AccessPathName (
m_tmp
.c_str()) != 0)
73
m_file
.reset (TFile::Open (
m_tmp
.c_str(),
"CREATE"
));
74
}
75
76
RCU_NEW_INVARIANT
(
this
);
77
}
78
79
80
81
DiskWriterXRD ::
82
~DiskWriterXRD ()
83
{
84
RCU_DESTROY_INVARIANT
(
this
);
85
86
if
(
m_file
!=
nullptr
)
87
{
88
try
89
{
90
close
();
91
}
catch
(std::exception& e)
92
{
93
std::cerr <<
"exception closing file "
<<
m_path
<<
": "
94
<< e.what() << std::endl;
95
96
}
catch
(...)
97
{
98
std::cerr <<
"unknown exception closing file "
<<
m_path
<< std::endl;
99
}
100
}
101
}
102
103
104
105
std::string DiskWriterXRD ::
106
getPath ()
const
107
{
108
RCU_READ_INVARIANT
(
this
);
109
return
m_path
;
110
}
111
112
113
114
TFile *DiskWriterXRD ::
115
getFile ()
116
{
117
RCU_CHANGE_INVARIANT
(
this
);
118
RCU_REQUIRE2_SOFT
(
m_file
!=
nullptr
,
"file already closed"
);
119
return
m_file
.get();
120
}
121
122
123
124
void
DiskWriterXRD ::
125
doClose ()
126
{
127
RCU_CHANGE_INVARIANT
(
this
);
128
RCU_REQUIRE2_SOFT
(
m_file
!=
nullptr
,
"file already closed"
);
129
130
if
(
m_file
->IsOpen())
131
{
132
m_file
->Write ();
133
if
(
m_file
->TestBit (TFile::kWriteError))
134
throw
std::runtime_error (
"failed to write to file: "
+
m_path
);
135
m_file
->Close ();
136
}
137
138
// rationale: the RNG is only needed on the retry path, and
139
// constructing std::random_device typically opens /dev/urandom,
140
// so we construct it lazily on first use.
141
std::optional<std::mt19937> gen;
142
bool
success =
false
;
143
unsigned
tries = 0u;
144
while
(!success)
145
{
146
try
147
{
148
// using the -f flag, because if this copy failed previously
149
// we need to force an overwrite. note that there would be no
150
// point in leaving this out on the first try (even though
151
// there should be no file there), because it would just fail
152
// and retry with the flag set.
153
RCU::Shell::exec
(
"xrdcp -f "
+
RCU::Shell::quote
(
m_tmp
) +
" "
+
RCU::Shell::quote
(
m_path
));
154
success =
true
;
155
}
catch
(...)
156
{
157
std::cerr <<
"encountered error copying files to XRD path: \""
<<
m_path
<<
"\""
<< std::endl;
158
if
(tries < 10u)
159
{
160
tries += 1;
161
if
(!gen)
162
{
163
std::random_device rd;
164
gen.emplace (rd());
165
}
166
// sleeping for a random period of time, to reduce the
167
// chance that the problem is that multiple jobs finishing
168
// at the same time keep overloading the server by
169
// repeatedly hitting it at the same time.
170
unsigned
seconds = std::uniform_int_distribution<>(30,60) (*gen);
171
std::cerr <<
"sleeping for "
<< seconds <<
" seconds before retrying"
<< std::endl;
172
std::this_thread::sleep_for (std::chrono::seconds(seconds));
173
}
else
174
{
175
std::cerr <<
"giving up, leaving file at "
<<
m_tmp
<< std::endl;
176
throw
std::runtime_error (
"failed to copy file to XRD"
);
177
}
178
}
179
}
180
// rationale: the upload has succeeded, so release the file handle
181
// now. that way a failure to remove the temporary file does not
182
// leave the writer looking un-closed and trigger a second upload
183
// from the destructor; a failed cleanup is only a warning.
184
m_file
.reset ();
185
try
186
{
187
RCU::Shell::exec
(
"rm "
+
RCU::Shell::quote
(
m_tmp
));
188
}
catch
(std::exception& e)
189
{
190
std::cerr <<
"failed to remove temporary file "
<<
m_tmp
<<
": "
191
<< e.what() << std::endl;
192
}
193
}
194
}
Assert.h
RCU_DESTROY_INVARIANT
#define RCU_DESTROY_INVARIANT(x)
Definition
Assert.h:223
RCU_CHANGE_INVARIANT
#define RCU_CHANGE_INVARIANT(x)
Definition
Assert.h:219
RCU_REQUIRE2_SOFT
#define RCU_REQUIRE2_SOFT(x, y)
Definition
Assert.h:143
RCU_NEW_INVARIANT
#define RCU_NEW_INVARIANT(x)
Definition
Assert.h:221
RCU_REQUIRE
#define RCU_REQUIRE(x)
Definition
Assert.h:196
RCU_READ_INVARIANT
#define RCU_READ_INVARIANT(x)
Definition
Assert.h:217
DiskWriterXRD.h
ShellExec.h
SH::DiskWriterXRD::m_tmp
std::string m_tmp
the temporary path being used
Definition
DiskWriterXRD.h:78
SH::DiskWriterXRD::m_path
std::string m_path
the path being used
Definition
DiskWriterXRD.h:82
SH::DiskWriterXRD::m_file
std::unique_ptr< TFile > m_file
the actual file object
Definition
DiskWriterXRD.h:86
SH::DiskWriter::close
void close()
closes the file we are writing to
Definition
DiskWriter.cxx:67
RCU::Shell::exec
void exec(const std::string &cmd)
effects: execute the given command guarantee: strong failures: out of memory II failures: system fail...
Definition
ShellExec.cxx:27
RCU::Shell::quote
std::string quote(const std::string &name)
effects: quote the given name to protect it from the shell returns: the quoted name guarantee: strong...
Definition
ShellExec.cxx:65
SH
This module provides a lot of global definitions, forward declarations and includes that are used by ...
Definition
DiskList.cxx:21
str
Definition
BTagTrackIpAccessor.cxx:11
Generated on
for ATLAS Offline Software by
1.17.0