CMS 3D CMS Logo

DCacheFile.cc
Go to the documentation of this file.
5 #include <cassert>
6 #include <vector>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <dcap.h>
10 
11 DCacheFile::DCacheFile(void) : m_fd(EDM_IOFD_INVALID), m_close(false) {}
12 
13 DCacheFile::DCacheFile(IOFD fd) : m_fd(fd), m_close(true) {}
14 
15 DCacheFile::DCacheFile(const char *name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */)
16  : m_fd(EDM_IOFD_INVALID), m_close(false) {
17  open(name, flags, perms);
18 }
19 
20 DCacheFile::DCacheFile(const std::string &name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */)
21  : m_fd(EDM_IOFD_INVALID), m_close(false) {
22  open(name.c_str(), flags, perms);
23 }
24 
26  if (m_close)
27  edm::LogError("DCacheFileError") << "Destructor called on dCache file '" << m_name
28  << "' but the file is still open";
29 }
30 
32 void DCacheFile::create(const char *name, bool exclusive /* = false */, int perms /* = 066 */) {
33  open(name,
35  perms);
36 }
37 
38 void DCacheFile::create(const std::string &name, bool exclusive /* = false */, int perms /* = 066 */) {
39  open(name.c_str(),
41  perms);
42 }
43 
44 void DCacheFile::open(const std::string &name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) {
45  open(name.c_str(), flags, perms);
46 }
47 
48 void DCacheFile::open(const char *name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) {
49  // Actual open
50  if ((name == nullptr) || (*name == 0)) {
52  ex << "Cannot open a file without a name";
53  ex.addContext("Calling DCacheFile::open()");
54  throw ex;
55  }
56 
57  if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0) {
59  ex << "Must open file '" << name << "' at least for read or write";
60  ex.addContext("Calling DCacheFile::open()");
61  throw ex;
62  }
63 
64  // If I am already open, close old file first
65  if (m_fd != EDM_IOFD_INVALID && m_close)
66  close();
67 
68  // Translate our flags to system flags
69  int openflags = 0;
70 
72  openflags |= O_RDWR;
73  else if (flags & IOFlags::OpenRead)
74  openflags |= O_RDONLY;
75  else if (flags & IOFlags::OpenWrite)
76  openflags |= O_WRONLY;
77 
79  openflags |= O_NONBLOCK;
80 
82  openflags |= O_APPEND;
83 
85  openflags |= O_CREAT;
86 
88  openflags |= O_EXCL;
89 
91  openflags |= O_TRUNC;
92 
93  IOFD newfd = EDM_IOFD_INVALID;
94  dc_errno = 0;
95  if ((newfd = dc_open(name, openflags, perms)) == -1) {
97  ex << "dc_open(name='" << name << "', flags=0x" << std::hex << openflags << ", permissions=0" << std::oct << perms
98  << std::dec << ") => error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")";
99  ex.addContext("Calling DCacheFile::open()");
100  throw ex;
101  }
102 
103  m_name = name;
104  m_fd = newfd;
105 
106  // Turn off read-ahead, or adjust read-ahead size depending on
107  // whether buffering has been requested. This is a very tricky
108  // balance here. Without read-ahead data processing appears to
109  // become exceedingly slow, and with default (1MB) read-ahead
110  // it appears to saturate disk servers and network. Try tread
111  // reasonable middle ground here.
113  dc_noBuffering(m_fd);
114  else
115  dc_setBufferSize(m_fd, 64000);
116 
117  m_close = true;
118 
119  edm::LogInfo("DCacheFileInfo") << "Opened " << m_name;
120 }
121 
122 void DCacheFile::close(void) {
123  if (m_fd == EDM_IOFD_INVALID) {
124  edm::LogError("DCacheFileError") << "DCacheFile::close(name='" << m_name << "') called but the file is not open";
125  m_close = false;
126  return;
127  }
128 
129  dc_errno = 0;
130  if (dc_close(m_fd) == -1)
131  edm::LogWarning("DCacheFileWarning") << "dc_close(name='" << m_name << "') failed with error '"
132  << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")";
133 
134  m_close = false;
136 
137  // Caused hang. Will be added back after problem is fixed.
138  // edm::LogInfo("DCacheFileInfo") << "Closed " << m_name;
139 }
140 
141 void DCacheFile::abort(void) {
142  if (m_fd != EDM_IOFD_INVALID)
143  dc_close(m_fd);
144 
145  m_close = false;
147 }
148 
150 static const int BUGLINE = __LINE__ + 1;
151 // Apparently dc_read can return short reads; I don't know if dc_write
152 // will also return short writes. This is a bug in dCache. POSIX,
153 // apparently contrary to the understanding of dCache authors, does
154 // not allow reads from files to return short, and in fact no network
155 // file system returns short reads. For more details please refer to
156 // http://www.opengroup.org/onlinepubs/000095399/functions/read.html:
157 // The value returned may be less than nbyte if the number of
158 // bytes left in the file is less than nbyte, if the read()
159 // request was interrupted by a signal, or if the file is a
160 // pipe or FIFO or special file and has fewer than nbyte bytes
161 // immediately available for reading.
162 // (In other words, barring signals (which should use SA_RESTART and
163 // in any case should not affect dCache) the only way a read from a
164 // file can return short is when there is nothing left to read.)
166  IOSize done = 0;
167  while (done < n) {
168  dc_errno = 0;
169  ssize_t s = dc_read(m_fd, (char *)into + done, n - done);
170  if (s == -1) {
172  ex << "dc_read(name='" << m_name << "', n=" << (n - done) << ") failed with error '" << dc_strerror(dc_errno)
173  << "' (dc_errno=" << dc_errno << ")";
174  ex.addContext("Calling DCacheFile::read()");
175  throw ex;
176  } else if (s == 0)
177  // end of file
178  break;
179  else if (s < ssize_t(n - done))
180  edm::LogInfo("DCacheFileWarning") << "dc_read(name='" << m_name << "', n=" << (n - done)
181  << ") returned a short read of " << s << " bytes; "
182  << "please report a bug in dCache referencing the "
183  << "comment on line " << BUGLINE << " of " << __FILE__;
184  done += s;
185  }
186 
187  return done;
188 }
189 
190 IOSize DCacheFile::write(const void *from, IOSize n) {
191  IOSize done = 0;
192  while (done < n) {
193  dc_errno = 0;
194  ssize_t s = dc_write(m_fd, (const char *)from + done, n - done);
195  if (s == -1) {
197  ex << "dc_write(name='" << m_name << "', n=" << (n - done) << ") failed with error '" << dc_strerror(dc_errno)
198  << "' (dc_errno=" << dc_errno << ")";
199  ex.addContext("Calling DCacheFile::write()");
200  throw ex;
201  } else if (s < ssize_t(n - done))
202  edm::LogInfo("DCacheFileWarning") << "dc_write(name='" << m_name << "', n=" << (n - done)
203  << ") returned a short write of " << s << " bytes; "
204  << "please report a bug in dCache referencing the "
205  << "comment on line " << BUGLINE << " of " << __FILE__;
206  done += s;
207  }
208 
209  return done;
210 }
211 
213  assert(!buffers || into);
214 
215  // readv may not support zero buffers.
216  if (!buffers)
217  return 0;
218 
219  // Convert the buffers to system format.
220  std::vector<iovec> bufs(buffers);
221  for (IOSize i = 0; i < buffers; ++i) {
222  bufs[i].iov_len = into[i].size();
223  bufs[i].iov_base = (caddr_t)into[i].data();
224  }
225 
226  // Read as long as signals cancel the read before doing anything.
227  dc_errno = 0;
228  ssize_t n = dc_readv(m_fd, &bufs[0], buffers);
229 
230  // If it was serious error, throw it.
231  if (n == -1) {
233  ex << "dc_readv(name='" << m_name << "', iov[" << buffers << "]) failed with error '" << dc_strerror(dc_errno)
234  << "' (dc_errno=" << dc_errno << ")";
235  ex.addContext("Calling DCacheFile::readv()");
236  throw ex;
237  }
238 
239  // Return the number of bytes actually read.
240  return n;
241 }
242 
244  assert(!buffers || into);
245 
246  // readv may not support zero buffers.
247  if (!buffers)
248  return 0;
249 
250  // Convert the buffers to system format.
251  std::vector<iovec2> bufs(buffers);
252  IOSize total = 0;
253  for (IOSize i = 0; i < buffers; ++i) {
254  bufs[i].offset = into[i].offset();
255  bufs[i].len = into[i].size();
256  bufs[i].buf = (char *)into[i].data();
257  total += into[i].size();
258  }
259 
260  // Read as long as signals cancel the read before doing anything.
261  dc_errno = 0;
262  ssize_t n = dc_readv2(m_fd, &bufs[0], buffers);
263 
264  // If it was serious error, throw it.
265  if (n == -1) {
267  ex << "dc_readv2(name='" << m_name << "', iov2[" << buffers << "]) failed with error '" << dc_strerror(dc_errno)
268  << "' (dc_errno=" << dc_errno << ")";
269  ex.addContext("Calling DCacheFile::readv()");
270  throw ex;
271  }
272  // dc_readv2 returns 0 on success.
273  return (n == 0) ? total : 0;
274 }
275 
280  if (m_fd == EDM_IOFD_INVALID) {
281  cms::Exception ex("FilePositionError");
282  ex << "DCacheFile::position() called on a closed file";
283  throw ex;
284  }
285  if (whence != CURRENT && whence != SET && whence != END) {
286  cms::Exception ex("FilePositionError");
287  ex << "DCacheFile::position() called with incorrect 'whence' parameter";
288  throw ex;
289  }
291  int mywhence = (whence == SET ? SEEK_SET : whence == CURRENT ? SEEK_CUR : SEEK_END);
292 
293  dc_errno = 0;
294  if ((result = dc_lseek64(m_fd, offset, mywhence)) == -1) {
295  cms::Exception ex("FilePositionError");
296  ex << "dc_lseek64(name='" << m_name << "', offset=" << offset << ", whence=" << mywhence << ") failed with error '"
297  << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")";
298  ex.addContext("Calling DCacheFile::position()");
299  throw ex;
300  }
301  // FIXME: dCache returns incorrect value on SEEK_END.
302  // Remove this hack when dcap has been fixed.
303  if (whence == SEEK_END && (result = dc_lseek64(m_fd, result, SEEK_SET)) == -1) {
304  cms::Exception ex("FilePositionError");
305  ex << "dc_lseek64(name='" << m_name << "', offset=" << offset << ", whence=" << SEEK_SET << ") failed with error '"
306  << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")";
307  ex.addContext("Calling DCacheFile::position()");
308  throw ex;
309  }
310  return result;
311 }
312 
313 void DCacheFile::resize(IOOffset /* size */) {
314  cms::Exception ex("FileResizeError");
315  ex << "DCacheFile::resize(name='" << m_name << "') not implemented";
316  throw ex;
317 }
DCacheFile::open
virtual void open(const char *name, int flags=IOFlags::OpenRead, int perms=0666)
Definition: DCacheFile.cc:48
DCacheFile::m_fd
IOFD m_fd
Definition: DCacheFile.h:37
DCacheFile::create
virtual void create(const char *name, bool exclusive=false, int perms=0666)
Definition: DCacheFile.cc:32
DCacheFile::m_close
bool m_close
Definition: DCacheFile.h:38
IOBuffer::size
IOSize size(void) const
Definition: IOBuffer.h:34
mps_fire.i
i
Definition: mps_fire.py:355
MessageLogger.h
funct::false
false
Definition: Factorize.h:34
dqmiodumpmetadata.n
n
Definition: dqmiodumpmetadata.py:28
cms::Exception::addContext
void addContext(std::string const &context)
Definition: Exception.cc:165
IOFlags::OpenNonBlock
Definition: IOFlags.h:9
edm::LogInfo
Definition: MessageLogger.h:254
Storage::END
Definition: Storage.h:22
Storage::SET
Definition: Storage.h:22
edm::errors::FileWriteError
Definition: EDMException.h:66
Storage::Relative
Relative
Definition: Storage.h:22
cms::cuda::assert
assert(be >=bs)
IOFlags::OpenTruncate
Definition: IOFlags.h:28
IOFlags::OpenWrite
Definition: IOFlags.h:8
edm::errors::FileOpenError
Definition: EDMException.h:49
edm::Exception
Definition: EDMException.h:77
EDMException.h
DCacheFile::m_name
std::string m_name
Definition: DCacheFile.h:39
ztee.fd
fd
Definition: ztee.py:136
alignCSCRings.s
s
Definition: alignCSCRings.py:92
fileCollector.done
done
Definition: fileCollector.py:123
DCacheFile::readv
IOSize readv(IOBuffer *into, IOSize buffers) override
Definition: DCacheFile.cc:212
IOFlags::OpenRead
Definition: IOFlags.h:7
AlCaHLTBitMon_QueryRunRegistry.string
string
Definition: AlCaHLTBitMon_QueryRunRegistry.py:256
edm::LogWarning
Definition: MessageLogger.h:141
funct::true
true
Definition: Factorize.h:173
DCacheFile.h
edm::LogError
Definition: MessageLogger.h:183
IOBuffer
Definition: IOBuffer.h:7
DCacheFile::close
void close(void) override
Definition: DCacheFile.cc:122
BUGLINE
static const int BUGLINE
Definition: DCacheFile.cc:150
IOOffset
int64_t IOOffset
Definition: IOTypes.h:19
IOFlags::OpenExclusive
Definition: IOFlags.h:25
IOFlags::OpenCreate
Definition: IOFlags.h:24
DCacheFile::resize
void resize(IOOffset size) override
Definition: DCacheFile.cc:313
IOFD
int IOFD
Definition: IOTypes.h:22
IOFlags::OpenAppend
Definition: IOFlags.h:18
DCacheFile::~DCacheFile
~DCacheFile(void) override
Definition: DCacheFile.cc:25
IOPosBuffer::size
IOSize size(void) const
Definition: IOPosBuffer.h:45
generator_cfi.exclusive
exclusive
Definition: generator_cfi.py:24
EDM_IOFD_INVALID
#define EDM_IOFD_INVALID
Definition: IOTypes.h:8
DCacheFile::DCacheFile
DCacheFile(void)
Definition: DCacheFile.cc:11
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
DCacheFile::abort
virtual void abort(void)
Definition: DCacheFile.cc:141
O_NONBLOCK
#define O_NONBLOCK
Definition: SysFile.h:21
Exception.h
data
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
Storage::CURRENT
Definition: Storage.h:22
dqmMemoryStats.total
total
Definition: dqmMemoryStats.py:152
IOPosBuffer
Definition: IOPosBuffer.h:7
IOFlags::OpenUnbuffered
Definition: IOFlags.h:20
mps_fire.result
result
Definition: mps_fire.py:303
cms::Exception
Definition: Exception.h:70
hltrates_dqm_sourceclient-live_cfg.offset
offset
Definition: hltrates_dqm_sourceclient-live_cfg.py:78
IOSize
size_t IOSize
Definition: IOTypes.h:14
edm::errors::FileReadError
Definition: EDMException.h:50
HLT_2018_cff.flags
flags
Definition: HLT_2018_cff.py:11758
TauDecayModes.dec
dec
Definition: TauDecayModes.py:143
DCacheFile::write
IOSize write(const void *from, IOSize n) override
Definition: DCacheFile.cc:190