CMS 3D CMS Logo

DavixFile.cc
Go to the documentation of this file.
5 #include <cassert>
6 #include <davix.hpp>
7 #include <cerrno>
8 #include <fcntl.h>
9 #include <cstdlib>
10 #include <unistd.h>
11 #include <vector>
12 #include <mutex>
13 
14 static std::once_flag davixDebugInit;
15 
16 using namespace Davix;
17 
19 
20 DavixFile::DavixFile(const char *name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) {
21  open(name, flags, perms);
22 }
23 
24 DavixFile::DavixFile(const std::string &name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) {
25  open(name.c_str(), flags, perms);
26 }
27 
29  close();
30  return;
31 }
32 
33 void DavixFile::close(void) {
34  if (m_davixPosix && m_fd) {
35  auto davixPosix = std::move(m_davixPosix);
36  DavixError *err = nullptr;
37  davixPosix->close(m_fd, &err);
38  m_fd = nullptr;
39  if (err) {
40  std::unique_ptr<DavixError> davixErrManaged(err);
41  cms::Exception ex("FileCloseError");
42  ex << "Davix::close(name='" << m_name << ") failed with error " << err->getErrMsg().c_str() << " and error code "
43  << err->getStatus();
44  ex.addContext("Calling DavixFile::close()");
45  throw ex;
46  }
47  }
48  return;
49 }
50 
51 void DavixFile::abort(void) {
52  if (m_davixPosix && m_fd) {
53  DavixError *err = nullptr;
54  m_davixPosix->close(m_fd, &err);
55  if (err) {
56  std::unique_ptr<DavixError> davixErrManaged(err);
57  cms::Exception ex("FileAbortError");
58  ex << "Davix::abort(name='" << m_name << ") failed with error " << err->getErrMsg().c_str() << " and error code "
59  << err->getStatus();
60  ex.addContext("Calling DavixFile::abort()");
61  throw ex;
62  }
63  }
64  return;
65 }
66 
68  long logLevel = 0;
69  char *logptr = nullptr;
70  char const *const davixDebug = std::getenv("Davix_Debug");
71  if (davixDebug != nullptr) {
72  logLevel = strtol(davixDebug, &logptr, 0);
73  if (errno) {
74  edm::LogWarning("DavixFile") << "Got error while converting "
75  << "Davix_Debug env variable to integer. "
76  "Will use default log level 0";
77  logLevel = 0;
78  }
79  if (logptr == davixDebug) {
80  edm::LogWarning("DavixFile") << "Failed to convert to integer "
81  << "Davix_Debug env variable; Will use default log level 0";
82  logLevel = 0;
83  } else if (*logptr != '\0') {
84  edm::LogWarning("DavixFile") << "Failed to parse extra junk "
85  << "from Davix_Debug env variable. Will use default log level 0";
86  logLevel = 0;
87  }
88  }
89  switch (logLevel) {
90  case 0:
91  std::call_once(davixDebugInit, davix_set_log_level, 0);
92  break;
93  case 1:
94  std::call_once(davixDebugInit, davix_set_log_level, DAVIX_LOG_WARNING);
95  break;
96  case 2:
97  std::call_once(davixDebugInit, davix_set_log_level, DAVIX_LOG_VERBOSE);
98  break;
99  case 3:
100  std::call_once(davixDebugInit, davix_set_log_level, DAVIX_LOG_DEBUG);
101  break;
102  default:
103  std::call_once(davixDebugInit, davix_set_log_level, DAVIX_LOG_ALL);
104  break;
105  }
106 }
107 
108 static int X509Authentication(void *userdata, const SessionInfo &info, X509Credential *cert, DavixError **davixErr) {
109  std::string ucert, ukey;
110  char default_proxy[64];
111  snprintf(default_proxy, sizeof(default_proxy), "/tmp/x509up_u%d", geteuid());
112  // X509_USER_PROXY
113  if (std::getenv("X509_USER_PROXY")) {
114  edm::LogInfo("DavixFile") << "X509_USER_PROXY found in environment."
115  << " Will use it for authentication";
116  ucert = ukey = std::getenv("X509_USER_PROXY");
117  }
118  // Default proxy location
119  else if (access(default_proxy, R_OK) == 0) {
120  edm::LogInfo("DavixFile") << "Found proxy in default location " << default_proxy
121  << " Will use it for authentication";
122  ucert = ukey = default_proxy;
123  }
124  // X509_USER_CERT
125  else if (std::getenv("X509_USER_CERT")) {
126  ucert = std::getenv("X509_USER_CERT");
127  }
128  // X509_USER_KEY only if X509_USER_CERT was found
129  if (!ucert.empty() && std::getenv("X509_USER_KEY")) {
130  edm::LogInfo("DavixFile") << "X509_USER_{CERT|KEY} found in environment"
131  << " Will use it for authentication";
132  ukey = std::getenv("X509_USER_KEY");
133  }
134  // Check if vars are set...
135  if (ucert.empty() || ukey.empty()) {
136  edm::LogWarning("DavixFile") << "Was not able to find proxy in $X509_USER_PROXY, "
137  << "X509_USER_{CERT|KEY} or default proxy creation location. "
138  << "Will try without authentication";
139  return -1;
140  }
141  return cert->loadFromFilePEM(ukey, ucert, "", davixErr);
142 }
143 
144 void DavixFile::create(const char *name, bool exclusive /* = false */, int perms /* = 066 */) {
145  open(name,
147  perms);
148 }
149 
150 void DavixFile::create(const std::string &name, bool exclusive /* = false */, int perms /* = 066 */) {
151  open(name.c_str(),
153  perms);
154 }
155 
156 void DavixFile::open(const std::string &name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) {
157  open(name.c_str(), flags, perms);
158 }
159 
160 void DavixFile::open(const char *name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) {
161  // Actual open
162  if ((name == nullptr) || (*name == 0)) {
164  ex << "Cannot open a file without name";
165  ex.addContext("Calling DavixFile::open()");
166  throw ex;
167  }
168  m_name = name;
169 
170  if ((flags & IOFlags::OpenRead) == 0) {
172  ex << "Must open file '" << name << "' at least for read";
173  ex.addContext("Calling DavixFile::open()");
174  throw ex;
175  }
176 
177  if (m_davixPosix && m_fd) {
179  ex << "Davix::open(name='" << m_name << "') failed on already open file";
180  ex.addContext("Calling DavixFile::open()");
181  throw ex;
182  }
183  configureDavixLogLevel();
184  // Translate our flags to system flags
185  int openflags = 0;
186 
187  if (flags & IOFlags::OpenRead)
188  openflags |= O_RDONLY;
189 
190  DavixError *davixErr = nullptr;
191  RequestParams davixReqParams;
192  // Set up X509 authentication
193  davixReqParams.setClientCertCallbackX509(&X509Authentication, nullptr);
194  // Set also CERT_DIR if it is set in envinroment, otherwise use default
195  const char *cert_dir = nullptr;
196  if ((cert_dir = std::getenv("X509_CERT_DIR")) == nullptr)
197  cert_dir = "/etc/grid-security/certificates";
198  davixReqParams.addCertificateAuthorityPath(cert_dir);
199 
200  m_davixPosix = std::make_unique<DavPosix>(new Context());
201  m_fd = m_davixPosix->open(&davixReqParams, name, openflags, &davixErr);
202 
203  // Check Davix Error
204  if (davixErr) {
205  std::unique_ptr<DavixError> davixErrManaged(davixErr);
207  ex << "Davix::open(name='" << m_name << "') failed with "
208  << "error '" << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus();
209  ex.addContext("Calling DavixFile::open()");
210  throw ex;
211  }
212  if (!m_fd) {
214  ex << "Davix::open(name='" << m_name << "') failed as fd is NULL";
215  ex.addContext("Calling DavixFile::open()");
216  throw ex;
217  }
218 }
219 
221  assert(!buffers || into);
222 
223  // Davix does not support 0 buffers;
224  if (buffers == 0)
225  return 0;
226 
227  DavixError *davixErr = nullptr;
228 
229  std::vector<DavIOVecInput> input_vector(buffers);
230  std::vector<DavIOVecOuput> output_vector(buffers);
231  IOSize total = 0; // Total requested bytes
232  for (IOSize i = 0; i < buffers; ++i) {
233  input_vector[i].diov_size = into[i].size();
234  input_vector[i].diov_buffer = static_cast<char *>(into[i].data());
235  total += into[i].size();
236  }
237 
238  ssize_t s = m_davixPosix->preadVec(m_fd, input_vector.data(), output_vector.data(), buffers, &davixErr);
239  if (davixErr) {
240  std::unique_ptr<DavixError> davixErrManaged(davixErr);
242  ex << "Davix::readv(name='" << m_name << "', buffers=" << (buffers) << ") failed with error "
243  << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus() << " and call returned " << s
244  << " bytes";
245  ex.addContext("Calling DavixFile::readv()");
246  throw ex;
247  }
248  // Davix limits number of requests sent to the server
249  // to improve performance and it does range coalescing.
250  // So we can`t check what preadVec returns with what was requested.
251  // Example: If two ranges are overlapping, [10, 20] and [20, 30] which is
252  // coalesced into [10, 30] and it will contain one less byte than was requested.
253  // Only check if returned val <= 0 and make proper actions.
254  if (s < 0) {
256  ex << "Davix::readv(name='" << m_name << "') failed and call returned " << s;
257  ex.addContext("Calling DavixFile::readv()");
258  throw ex;
259  } else if (s == 0) {
260  // end of file
261  return 0;
262  }
263  return total;
264 }
265 
267  assert(!buffers || into);
268 
269  // Davix does not support 0 buffers;
270  if (buffers == 0)
271  return 0;
272 
273  DavixError *davixErr = nullptr;
274 
275  std::vector<DavIOVecInput> input_vector(buffers);
276  std::vector<DavIOVecOuput> output_vector(buffers);
277  IOSize total = 0;
278  for (IOSize i = 0; i < buffers; ++i) {
279  input_vector[i].diov_offset = into[i].offset();
280  input_vector[i].diov_size = into[i].size();
281  input_vector[i].diov_buffer = static_cast<char *>(into[i].data());
282  total += into[i].size();
283  }
284  ssize_t s = m_davixPosix->preadVec(m_fd, input_vector.data(), output_vector.data(), buffers, &davixErr);
285  if (davixErr) {
286  std::unique_ptr<DavixError> davixErrManaged(davixErr);
288  ex << "Davix::readv(name='" << m_name << "', n=" << buffers << ") failed with error "
289  << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus() << " and call returned " << s
290  << " bytes";
291  ex.addContext("Calling DavixFile::readv()");
292  throw ex;
293  }
294  // Davix limits number of requests sent to the server
295  // to improve performance and it does range coalescing.
296  // So we can`t check what preadVec returns with what was requested.
297  // Example: If two ranges are overlapping, [10, 20] and [20, 30] which is
298  // coalesced into [10, 30] and it will contain one less byte than was requested.
299  // Only check if returned val <= 0 and make proper actions.
300  if (s < 0) {
302  ex << "Davix::readv(name='" << m_name << "', n=" << buffers << ") failed and call returned " << s;
303  ex.addContext("Calling DavixFile::readv()");
304  throw ex;
305  } else if (s == 0) {
306  // end of file
307  return 0;
308  }
309  return total;
310 }
311 
313  DavixError *davixErr = nullptr;
314  m_davixPosix->fadvise(m_fd, 0, n, AdviseRandom);
315  IOSize done = 0;
316  while (done < n) {
317  ssize_t s = m_davixPosix->read(m_fd, (char *)into + done, n - done, &davixErr);
318  if (davixErr) {
319  std::unique_ptr<DavixError> davixErrManaged(davixErr);
321  ex << "Davix::read(name='" << m_name << "', n=" << (n - done) << ") failed with error "
322  << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus() << " and call returned " << s
323  << " bytes";
324  ex.addContext("Calling DavixFile::read()");
325  throw ex;
326  }
327  if (s < 0) {
329  ex << "Davix::read(name='" << m_name << "', n=" << (n - done) << ") failed and call returned " << s;
330  ex.addContext("Calling DavixFile::read()");
331  throw ex;
332  } else if (s == 0) {
333  // end of file
334  break;
335  }
336  done += s;
337  }
338  return done;
339 }
340 
341 IOSize DavixFile::write(const void *from, IOSize n) {
343  ex << "DavixFile::write(name='" << m_name << "') not implemented";
344  ex.addContext("Calling DavixFile::write()");
345  throw ex;
346 }
347 
349  DavixError *davixErr = nullptr;
350  if (whence != CURRENT && whence != SET && whence != END) {
351  cms::Exception ex("FilePositionError");
352  ex << "DavixFile::position() called with incorrect 'whence' parameter";
353  ex.addContext("Calling DavixFile::position()");
354  throw ex;
355  }
357  size_t mywhence = (whence == SET ? SEEK_SET : whence == CURRENT ? SEEK_CUR : SEEK_END);
358 
359  if ((result = m_davixPosix->lseek(m_fd, offset, mywhence, &davixErr)) == -1) {
360  cms::Exception ex("FilePositionError");
361  ex << "Davix::lseek(name='" << m_name << "', offset=" << offset << ", whence=" << mywhence << ") failed with error "
362  << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus() << " and "
363  << "call returned " << result;
364  ex.addContext("Calling DavixFile::position()");
365  throw ex;
366  }
367 
368  return result;
369 }
370 
371 void DavixFile::resize(IOOffset /* size */) {
372  cms::Exception ex("FileResizeError");
373  ex << "DavixFile::resize(name='" << m_name << "') not implemented";
374  ex.addContext("Calling DavixFile::resize()");
375  throw ex;
376 }
IOBuffer::size
IOSize size(void) const
Definition: IOBuffer.h:34
mps_fire.i
i
Definition: mps_fire.py:428
MessageLogger.h
X509Authentication
static int X509Authentication(void *userdata, const SessionInfo &info, X509Credential *cert, DavixError **davixErr)
Definition: DavixFile.cc:108
dqmiodumpmetadata.n
n
Definition: dqmiodumpmetadata.py:28
cms::Exception::addContext
void addContext(std::string const &context)
Definition: Exception.cc:165
L1DTConfigBti_cff.SET
SET
Definition: L1DTConfigBti_cff.py:21
DavixFile::close
void close(void) override
Definition: DavixFile.cc:33
davixDebugInit
static std::once_flag davixDebugInit
Definition: DavixFile.cc:14
edm::errors::FileWriteError
Definition: EDMException.h:66
Storage::Relative
Relative
Definition: Storage.h:22
cms::cuda::assert
assert(be >=bs)
DavixFile::resize
void resize(IOOffset size) override
Definition: DavixFile.cc:371
info
static const TGPicture * info(bool iBackgroundIsBlack)
Definition: FWCollectionSummaryWidget.cc:153
Context
IOFlags::OpenTruncate
Definition: IOFlags.h:28
IOFlags::OpenWrite
Definition: IOFlags.h:8
edm::LogInfo
Log< level::Info, false > LogInfo
Definition: MessageLogger.h:125
DavixFile::configureDavixLogLevel
static void configureDavixLogLevel()
Definition: DavixFile.cc:67
edm::LogWarning
Log< level::Warning, false > LogWarning
Definition: MessageLogger.h:122
edm::errors::FileOpenError
Definition: EDMException.h:49
edm::Exception
Definition: EDMException.h:77
EDMException.h
DavixFile::~DavixFile
~DavixFile(void) override
Definition: DavixFile.cc:28
alignCSCRings.s
s
Definition: alignCSCRings.py:92
fileCollector.done
done
Definition: fileCollector.py:123
IOFlags::OpenRead
Definition: IOFlags.h:7
DavixFile::readv
IOSize readv(IOBuffer *into, IOSize buffers) override
Definition: DavixFile.cc:220
AlCaHLTBitMon_QueryRunRegistry.string
string
Definition: AlCaHLTBitMon_QueryRunRegistry.py:256
DavixFile::create
virtual void create(const char *name, bool exclusive=false, int perms=0666)
Definition: DavixFile.cc:144
DavixFile::write
IOSize write(const void *from, IOSize n) override
Definition: DavixFile.cc:341
IOBuffer
Definition: IOBuffer.h:7
IOOffset
int64_t IOOffset
Definition: IOTypes.h:19
IOFlags::OpenExclusive
Definition: IOFlags.h:25
IOFlags::OpenCreate
Definition: IOFlags.h:24
submitPVResolutionJobs.err
err
Definition: submitPVResolutionJobs.py:85
DavixFile::open
virtual void open(const char *name, int flags=IOFlags::OpenRead, int perms=0666)
Definition: DavixFile.cc:160
eostools.move
def move(src, dest)
Definition: eostools.py:511
IOPosBuffer::size
IOSize size(void) const
Definition: IOPosBuffer.h:45
generator_cfi.exclusive
exclusive
Definition: generator_cfi.py:24
IOPosBuffer::offset
IOOffset offset(void) const
Definition: IOPosBuffer.h:39
Storage::position
virtual IOOffset position(void) const
Definition: Storage.cc:72
IOInput::read
int read(void)
Definition: IOInput.cc:52
Skims_PA_cff.name
name
Definition: Skims_PA_cff.py:17
Exception.h
data
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
dqmMemoryStats.total
total
Definition: dqmMemoryStats.py:152
IOPosBuffer
Definition: IOPosBuffer.h:7
DavixFile::abort
virtual void abort(void)
Definition: DavixFile.cc:51
mps_fire.result
result
Definition: mps_fire.py:311
cms::Exception
Definition: Exception.h:70
DavixFile.h
DavixFile::DavixFile
DavixFile(void)
Definition: DavixFile.cc:18
hltrates_dqm_sourceclient-live_cfg.offset
offset
Definition: hltrates_dqm_sourceclient-live_cfg.py:82
IOSize
size_t IOSize
Definition: IOTypes.h:14
HLT_FULL_cff.flags
flags
Definition: HLT_FULL_cff.py:13216
edm::errors::FileReadError
Definition: EDMException.h:50