CMS 3D CMS Logo

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