CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
XrdFile.cc
Go to the documentation of this file.
7 #include <vector>
8 #include <sstream>
9 
11  : m_client (0),
12  m_offset (0),
13  m_stat(),
14  m_close (false),
15  m_name()
16 {
17  memset(&m_stat, 0, sizeof (m_stat));
18  pthread_mutex_init(&m_readv_mutex, 0);
19 }
20 
21 XrdFile::XrdFile (const char *name,
22  int flags /* = IOFlags::OpenRead */,
23  int perms /* = 066 */)
24  : m_client (0),
25  m_offset (0),
26  m_stat(),
27  m_close (false),
28  m_name()
29 {
30  memset(&m_stat, 0, sizeof (m_stat));
31  pthread_mutex_init(&m_readv_mutex, 0);
32  open (name, flags, perms);
33 }
34 
36  int flags /* = IOFlags::OpenRead */,
37  int perms /* = 066 */)
38  : m_client (0),
39  m_offset (0),
40  m_stat(),
41  m_close (false),
42  m_name()
43 {
44  memset(&m_stat, 0, sizeof (m_stat));
45  pthread_mutex_init(&m_readv_mutex, 0);
46  open (name.c_str (), flags, perms);
47 }
48 
50 {
51  if (m_close)
52  edm::LogError("XrdFileError")
53  << "Destructor called on XROOTD file '" << m_name
54  << "' but the file is still open";
55  pthread_mutex_destroy(&m_readv_mutex);
56 }
57 
59 void
60 XrdFile::create (const char *name,
61  bool exclusive /* = false */,
62  int perms /* = 066 */)
63 {
64  open (name,
66  | (exclusive ? IOFlags::OpenExclusive : 0)),
67  perms);
68 }
69 
70 void
72  bool exclusive /* = false */,
73  int perms /* = 066 */)
74 {
75  open (name.c_str (),
77  | (exclusive ? IOFlags::OpenExclusive : 0)),
78  perms);
79 }
80 
81 void
83  int flags /* = IOFlags::OpenRead */,
84  int perms /* = 066 */)
85 { open (name.c_str (), flags, perms); }
86 
87 void
88 XrdFile::open (const char *name,
89  int flags /* = IOFlags::OpenRead */,
90  int perms /* = 066 */)
91 {
92  // Actual open
93  if ((name == 0) || (*name == 0)) {
95  ex << "Cannot open a file without a name";
96  ex.addContext("Calling XrdFile::open()");
97  throw ex;
98  }
99  if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0) {
101  ex << "Must open file '" << name << "' at least for read or write";
102  ex.addContext("Calling XrdFile::open()");
103  throw ex;
104  }
105  // If I am already open, close old file first
106  if (m_client && m_close)
107  close();
108  else
109  abort();
110 
111  // Translate our flags to system flags
112  int openflags = 0;
113 
114  if (flags & IOFlags::OpenWrite)
115  openflags |= kXR_open_updt;
116  else if (flags & IOFlags::OpenRead)
117  openflags |= kXR_open_read;
118 
119  if (flags & IOFlags::OpenAppend) {
121  ex << "Opening file '" << name << "' in append mode not supported";
122  ex.addContext("Calling XrdFile::open()");
123  throw ex;
124  }
125 
126  if (flags & IOFlags::OpenCreate)
127  {
128  if (! (flags & IOFlags::OpenExclusive))
129  openflags |= kXR_delete;
130  openflags |= kXR_new;
131  openflags |= kXR_mkpath;
132  }
133 
134  if ((flags & IOFlags::OpenTruncate) && (flags & IOFlags::OpenWrite))
135  openflags |= kXR_delete;
136 
137  m_name = name;
138  m_client = new XrdClient(name);
139  m_client->UseCache(false); // Hack from Prof. Bockelman
140 
141  if (! m_client->Open(perms, openflags)
142  || m_client->LastServerResp()->status != kXR_ok) {
144  ex << "XrdClient::Open(name='" << name
145  << "', flags=0x" << std::hex << openflags
146  << ", permissions=0" << std::oct << perms << std::dec
147  << ") => error '" << m_client->LastServerError()->errmsg
148  << "' (errno=" << m_client->LastServerError()->errnum << ")";
149  ex.addContext("Calling XrdFile::open()");
150  addConnection(ex);
151  throw ex;
152  }
153  if (! m_client->Stat(&m_stat)) {
155  ex << "XrdClient::Stat(name='" << name
156  << ") => error '" << m_client->LastServerError()->errmsg
157  << "' (errno=" << m_client->LastServerError()->errnum << ")";
158  ex.addContext("Calling XrdFile::open()");
159  addConnection(ex);
160  throw ex;
161  }
162  m_offset = 0;
163  m_close = true;
164 
165  // Send the monitoring info, if available.
166  // Note: getenv is not reentrant.
167  const char * crabJobId = edm::storage::StatisticsSenderService::getJobID();
168  if (crabJobId) {
169  kXR_unt32 dictId;
170  m_client->SendMonitoringInfo(crabJobId, &dictId);
171  edm::LogInfo("XrdFileInfo") << "Set monitoring ID to " << crabJobId << " with resulting dictId " << dictId << ".";
172  }
173 
174  edm::LogInfo("XrdFileInfo") << "Opened " << m_name;
175 
176  XrdClientConn *conn = m_client->GetClientConn();
177  edm::LogInfo("XrdFileInfo") << "Connection URL " << conn->GetCurrentUrl().GetUrl().c_str();
178 
179  std::string host = std::string(conn->GetCurrentUrl().Host.c_str());
181  if (statsService.isAvailable()) {
182  statsService->setCurrentServer(host);
183  }
184 }
185 
186 void
188 {
189  if (! m_client)
190  {
191  edm::LogError("XrdFileError")
192  << "XrdFile::close(name='" << m_name
193  << "') called but the file is not open";
194  m_close = false;
195  return;
196  }
197 
198  if (! m_client->Close())
199  edm::LogWarning("XrdFileWarning")
200  << "XrdFile::close(name='" << m_name
201  << "') failed with error '" << m_client->LastServerError()->errmsg
202  << "' (errno=" << m_client->LastServerError()->errnum << ")";
203  delete m_client;
204  m_client = 0;
205 
206  m_close = false;
207  m_offset = 0;
208  memset(&m_stat, 0, sizeof (m_stat));
209  edm::LogInfo("XrdFileInfo") << "Closed " << m_name;
210 }
211 
212 void
214 {
215  delete m_client;
216  m_client = 0;
217  m_close = false;
218  m_offset = 0;
219  memset(&m_stat, 0, sizeof (m_stat));
220 }
221 
223 IOSize
224 XrdFile::read (void *into, IOSize n)
225 {
226  if (n > 0x7fffffff) {
228  ex << "XrdFile::read(name='" << m_name << "', n=" << n
229  << ") too many bytes, limit is 0x7fffffff";
230  ex.addContext("Calling XrdFile::read()");
231  addConnection(ex);
232  throw ex;
233  }
234  int s = m_client->Read(into, m_offset, n);
235  if (s < 0) {
237  ex << "XrdClient::Read(name='" << m_name
238  << "', offset=" << m_offset << ", n=" << n
239  << ") failed with error '" << m_client->LastServerError()->errmsg
240  << "' (errno=" << m_client->LastServerError()->errnum << ")";
241  ex.addContext("Calling XrdFile::read()");
242  addConnection(ex);
243  throw ex;
244  }
245  m_offset += s;
246  return s;
247 }
248 
249 IOSize
250 XrdFile::read (void *into, IOSize n, IOOffset pos)
251 {
252  if (n > 0x7fffffff) {
254  ex << "XrdFile::read(name='" << m_name << "', n=" << n
255  << ") exceeds read size limit 0x7fffffff";
256  ex.addContext("Calling XrdFile::read()");
257  addConnection(ex);
258  throw ex;
259  }
260  int s = m_client->Read(into, pos, n);
261  if (s < 0) {
263  ex << "XrdClient::Read(name='" << m_name
264  << "', offset=" << m_offset << ", n=" << n
265  << ") failed with error '" << m_client->LastServerError()->errmsg
266  << "' (errno=" << m_client->LastServerError()->errnum << ")";
267  ex.addContext("Calling XrdFile::read()");
268  addConnection(ex);
269  throw ex;
270  }
271  return s;
272 }
273 
274 IOSize
275 XrdFile::write (const void *from, IOSize n)
276 {
277  if (n > 0x7fffffff) {
278  cms::Exception ex("FileWriteError");
279  ex << "XrdFile::write(name='" << m_name << "', n=" << n
280  << ") too many bytes, limit is 0x7fffffff";
281  ex.addContext("Calling XrdFile::write()");
282  addConnection(ex);
283  throw ex;
284  }
285  ssize_t s = m_client->Write(from, m_offset, n);
286  if (s < 0) {
287  cms::Exception ex("FileWriteError");
288  ex << "XrdFile::write(name='" << m_name << "', n=" << n
289  << ") failed with error '" << m_client->LastServerError()->errmsg
290  << "' (errno=" << m_client->LastServerError()->errnum << ")";
291  ex.addContext("Calling XrdFile::write()");
292  addConnection(ex);
293  throw ex;
294  }
295  m_offset += s;
296  if (m_offset > m_stat.size)
297  m_stat.size = m_offset;
298 
299  return s;
300 }
301 
302 IOSize
303 XrdFile::write (const void *from, IOSize n, IOOffset pos)
304 {
305  if (n > 0x7fffffff) {
306  cms::Exception ex("FileWriteError");
307  ex << "XrdFile::write(name='" << m_name << "', n=" << n
308  << ") too many bytes, limit is 0x7fffffff";
309  ex.addContext("Calling XrdFile::write()");
310  addConnection(ex);
311  throw ex;
312  }
313  ssize_t s = m_client->Write(from, pos, n);
314  if (s < 0) {
315  cms::Exception ex("FileWriteError");
316  ex << "XrdFile::write(name='" << m_name << "', n=" << n
317  << ") failed with error '" << m_client->LastServerError()->errmsg
318  << "' (errno=" << m_client->LastServerError()->errnum << ")";
319  ex.addContext("Calling XrdFile::write()");
320  addConnection(ex);
321  throw ex;
322  }
323  if (pos + s > m_stat.size)
324  m_stat.size = pos + s;
325 
326  return s;
327 }
328 
329 bool
331 {
332  // Detect a prefetch support probe, and claim we don't support it.
333  // This will make the default application-only mode, but allows us to still
334  // effectively support storage-only mode.
335  if (unlikely((n == 1) && (what[0].offset() == 0) && (what[0].size() == PREFETCH_PROBE_LENGTH))) {
336  return false;
337  }
338  std::vector<long long> offsets; offsets.resize(n);
339  std::vector<int> lens; lens.resize(n);
340  kXR_int64 total = 0;
341  for (IOSize i = 0; i < n; ++i) {
342  offsets[i] = what[i].offset();
343  lens[i] = what[i].size();
344  total += what[i].size();
345  }
346 
347  kXR_int64 r = m_client->ReadV(NULL, &offsets[0], &lens[0], n);
348  return r == total;
349 }
350 
354 IOOffset
356 {
357  if (! m_client) {
358  cms::Exception ex("FilePositionError");
359  ex << "XrdFile::position() called on a closed file";
360  ex.addContext("Calling XrdFile::position()");
361  addConnection(ex);
362  throw ex;
363  }
364  switch (whence)
365  {
366  case SET:
367  m_offset = offset;
368  break;
369 
370  case CURRENT:
371  m_offset += offset;
372  break;
373 
374  case END:
375  m_offset = m_stat.size + offset;
376  break;
377 
378  default:
379  cms::Exception ex("FilePositionError");
380  ex << "XrdFile::position() called with incorrect 'whence' parameter";
381  ex.addContext("Calling XrdFile::position()");
382  addConnection(ex);
383  throw ex;
384  }
385 
386  if (m_offset < 0)
387  m_offset = 0;
388  if (m_offset > m_stat.size)
389  m_stat.size = m_offset;
390 
391  return m_offset;
392 }
393 
394 void
396 {
397  cms::Exception ex("FileResizeError");
398  ex << "XrdFile::resize(name='" << m_name << "') not implemented";
399  ex.addContext("Calling XrdFile::resize()");
400  addConnection(ex);
401  throw ex;
402 }
403 
404 void
406 {
407  XrdClientConn *conn = m_client->GetClientConn();
408  if (conn) {
409  std::stringstream ss;
410  ss << "Current server connection: " << conn->GetCurrentUrl().GetUrl().c_str();
411  ex.addAdditionalInfo(ss.str());
412  }
413 }
414 
virtual void resize(IOOffset size)
Definition: XrdFile.cc:395
int i
Definition: DBlmapReader.cc:9
#define PREFETCH_PROBE_LENGTH
Definition: Storage.h:18
virtual void close(void)
Definition: XrdFile.cc:187
XrdClientStatInfo m_stat
Definition: XrdFile.h:63
virtual void create(const char *name, bool exclusive=false, int perms=0666)
Definition: XrdFile.cc:60
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
#define NULL
Definition: scimark2.h:8
bool m_close
Definition: XrdFile.h:64
IOOffset m_offset
Definition: XrdFile.h:62
Relative
Definition: Storage.h:23
#define unlikely(x)
virtual bool prefetch(const IOPosBuffer *what, IOSize n)
Definition: XrdFile.cc:330
XrdFile(void)
Definition: XrdFile.cc:10
virtual IOOffset position(void) const
Definition: Storage.cc:95
void addAdditionalInfo(std::string const &info)
Definition: Exception.cc:235
int read(void)
Definition: IOInput.cc:54
unsigned int offset(bool)
XrdClient * m_client
Definition: XrdFile.h:61
IOOffset offset(void) const
Definition: IOPosBuffer.h:54
std::string m_name
Definition: XrdFile.h:65
string host
Definition: query.py:114
IOSize size(void) const
Definition: IOPosBuffer.h:64
~XrdFile(void)
Definition: XrdFile.cc:49
virtual IOOffset size(void) const
Definition: Storage.cc:102
void addContext(std::string const &context)
Definition: Exception.cc:227
int64_t IOOffset
Definition: IOTypes.h:19
pthread_mutex_t m_readv_mutex
Definition: XrdFile.h:68
size_t IOSize
Definition: IOTypes.h:14
volatile std::atomic< bool > shutdown_flag false
void addConnection(cms::Exception &)
Definition: XrdFile.cc:405
virtual void open(const char *name, int flags=IOFlags::OpenRead, int perms=0666)
Definition: XrdFile.cc:88
virtual IOSize write(const void *from, IOSize n)
Definition: XrdFile.cc:275
tuple conn
Definition: results_mgr.py:53
virtual void abort(void)
Definition: XrdFile.cc:213