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  if (! m_client->Open(perms, openflags)
140  || m_client->LastServerResp()->status != kXR_ok) {
142  ex << "XrdClient::Open(name='" << name
143  << "', flags=0x" << std::hex << openflags
144  << ", permissions=0" << std::oct << perms << std::dec
145  << ") => error '" << m_client->LastServerError()->errmsg
146  << "' (errno=" << m_client->LastServerError()->errnum << ")";
147  ex.addContext("Calling XrdFile::open()");
148  addConnection(ex);
149  throw ex;
150  }
151  if (! m_client->Stat(&m_stat)) {
153  ex << "XrdClient::Stat(name='" << name
154  << ") => error '" << m_client->LastServerError()->errmsg
155  << "' (errno=" << m_client->LastServerError()->errnum << ")";
156  ex.addContext("Calling XrdFile::open()");
157  addConnection(ex);
158  throw ex;
159  }
160  m_offset = 0;
161  m_close = true;
162 
163  // Send the monitoring info, if available.
164  // Note: getenv is not reentrant.
165  const char * crabJobId = edm::storage::StatisticsSenderService::getJobID();
166  if (crabJobId) {
167  kXR_unt32 dictId;
168  m_client->SendMonitoringInfo(crabJobId, &dictId);
169  edm::LogInfo("XrdFileInfo") << "Set monitoring ID to " << crabJobId << " with resulting dictId " << dictId << ".";
170  }
171 
172  edm::LogInfo("XrdFileInfo") << "Opened " << m_name;
173 
174  XrdClientConn *conn = m_client->GetClientConn();
175  edm::LogInfo("XrdFileInfo") << "Connection URL " << conn->GetCurrentUrl().GetUrl().c_str();
176 
177  std::string host = std::string(conn->GetCurrentUrl().Host.c_str());
179  if (statsService.isAvailable()) {
180  statsService->setCurrentServer(host);
181  }
182 }
183 
184 void
186 {
187  if (! m_client)
188  {
189  edm::LogError("XrdFileError")
190  << "XrdFile::close(name='" << m_name
191  << "') called but the file is not open";
192  m_close = false;
193  return;
194  }
195 
196  if (! m_client->Close())
197  edm::LogWarning("XrdFileWarning")
198  << "XrdFile::close(name='" << m_name
199  << "') failed with error '" << m_client->LastServerError()->errmsg
200  << "' (errno=" << m_client->LastServerError()->errnum << ")";
201  delete m_client;
202  m_client = 0;
203 
204  m_close = false;
205  m_offset = 0;
206  memset(&m_stat, 0, sizeof (m_stat));
207  edm::LogInfo("XrdFileInfo") << "Closed " << m_name;
208 }
209 
210 void
212 {
213  delete m_client;
214  m_client = 0;
215  m_close = false;
216  m_offset = 0;
217  memset(&m_stat, 0, sizeof (m_stat));
218 }
219 
221 IOSize
222 XrdFile::read (void *into, IOSize n)
223 {
224  if (n > 0x7fffffff) {
226  ex << "XrdFile::read(name='" << m_name << "', n=" << n
227  << ") too many bytes, limit is 0x7fffffff";
228  ex.addContext("Calling XrdFile::read()");
229  addConnection(ex);
230  throw ex;
231  }
232  int s = m_client->Read(into, m_offset, n);
233  if (s < 0) {
235  ex << "XrdClient::Read(name='" << m_name
236  << "', offset=" << m_offset << ", n=" << n
237  << ") failed with error '" << m_client->LastServerError()->errmsg
238  << "' (errno=" << m_client->LastServerError()->errnum << ")";
239  ex.addContext("Calling XrdFile::read()");
240  addConnection(ex);
241  throw ex;
242  }
243  m_offset += s;
244  return s;
245 }
246 
247 IOSize
249 {
250  if (n > 0x7fffffff) {
252  ex << "XrdFile::read(name='" << m_name << "', n=" << n
253  << ") exceeds read size limit 0x7fffffff";
254  ex.addContext("Calling XrdFile::read()");
255  addConnection(ex);
256  throw ex;
257  }
258  int s = m_client->Read(into, pos, n);
259  if (s < 0) {
261  ex << "XrdClient::Read(name='" << m_name
262  << "', offset=" << m_offset << ", n=" << n
263  << ") failed with error '" << m_client->LastServerError()->errmsg
264  << "' (errno=" << m_client->LastServerError()->errnum << ")";
265  ex.addContext("Calling XrdFile::read()");
266  addConnection(ex);
267  throw ex;
268  }
269  return s;
270 }
271 
272 IOSize
273 XrdFile::write (const void *from, IOSize n)
274 {
275  if (n > 0x7fffffff) {
276  cms::Exception ex("FileWriteError");
277  ex << "XrdFile::write(name='" << m_name << "', n=" << n
278  << ") too many bytes, limit is 0x7fffffff";
279  ex.addContext("Calling XrdFile::write()");
280  addConnection(ex);
281  throw ex;
282  }
283  ssize_t s = m_client->Write(from, m_offset, n);
284  if (s < 0) {
285  cms::Exception ex("FileWriteError");
286  ex << "XrdFile::write(name='" << m_name << "', n=" << n
287  << ") failed with error '" << m_client->LastServerError()->errmsg
288  << "' (errno=" << m_client->LastServerError()->errnum << ")";
289  ex.addContext("Calling XrdFile::write()");
290  addConnection(ex);
291  throw ex;
292  }
293  m_offset += s;
294  if (m_offset > m_stat.size)
295  m_stat.size = m_offset;
296 
297  return s;
298 }
299 
300 IOSize
301 XrdFile::write (const void *from, IOSize n, IOOffset pos)
302 {
303  if (n > 0x7fffffff) {
304  cms::Exception ex("FileWriteError");
305  ex << "XrdFile::write(name='" << m_name << "', n=" << n
306  << ") too many bytes, limit is 0x7fffffff";
307  ex.addContext("Calling XrdFile::write()");
308  addConnection(ex);
309  throw ex;
310  }
311  ssize_t s = m_client->Write(from, pos, n);
312  if (s < 0) {
313  cms::Exception ex("FileWriteError");
314  ex << "XrdFile::write(name='" << m_name << "', n=" << n
315  << ") failed with error '" << m_client->LastServerError()->errmsg
316  << "' (errno=" << m_client->LastServerError()->errnum << ")";
317  ex.addContext("Calling XrdFile::write()");
318  addConnection(ex);
319  throw ex;
320  }
321  if (pos + s > m_stat.size)
322  m_stat.size = pos + s;
323 
324  return s;
325 }
326 
327 bool
329 {
330  // Detect a prefetch support probe, and claim we don't support it.
331  // This will make the default application-only mode, but allows us to still
332  // effectively support storage-only mode.
333  if (unlikely((n == 1) && (what[0].offset() == 0) && (what[0].size() == PREFETCH_PROBE_LENGTH))) {
334  return false;
335  }
336  std::vector<long long> offsets; offsets.resize(n);
337  std::vector<int> lens; lens.resize(n);
338  kXR_int64 total = 0;
339  for (IOSize i = 0; i < n; ++i) {
340  offsets[i] = what[i].offset();
341  lens[i] = what[i].size();
342  total += what[i].size();
343  }
344 
345  kXR_int64 r = m_client->ReadV(NULL, &offsets[0], &lens[0], n);
346  return r == total;
347 }
348 
352 IOOffset
354 {
355  if (! m_client) {
356  cms::Exception ex("FilePositionError");
357  ex << "XrdFile::position() called on a closed file";
358  ex.addContext("Calling XrdFile::position()");
359  addConnection(ex);
360  throw ex;
361  }
362  switch (whence)
363  {
364  case SET:
365  m_offset = offset;
366  break;
367 
368  case CURRENT:
369  m_offset += offset;
370  break;
371 
372  case END:
373  m_offset = m_stat.size + offset;
374  break;
375 
376  default:
377  cms::Exception ex("FilePositionError");
378  ex << "XrdFile::position() called with incorrect 'whence' parameter";
379  ex.addContext("Calling XrdFile::position()");
380  addConnection(ex);
381  throw ex;
382  }
383 
384  if (m_offset < 0)
385  m_offset = 0;
386  if (m_offset > m_stat.size)
387  m_stat.size = m_offset;
388 
389  return m_offset;
390 }
391 
392 void
394 {
395  cms::Exception ex("FileResizeError");
396  ex << "XrdFile::resize(name='" << m_name << "') not implemented";
397  ex.addContext("Calling XrdFile::resize()");
398  addConnection(ex);
399  throw ex;
400 }
401 
402 void
404 {
405  XrdClientConn *conn = m_client->GetClientConn();
406  if (conn) {
407  std::stringstream ss;
408  ss << "Current server connection: " << conn->GetCurrentUrl().GetUrl().c_str();
409  ex.addAdditionalInfo(ss.str());
410  }
411 }
412 
virtual void resize(IOOffset size)
Definition: XrdFile.cc:393
int i
Definition: DBlmapReader.cc:9
#define PREFETCH_PROBE_LENGTH
Definition: Storage.h:18
virtual void close(void)
Definition: XrdFile.cc:185
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)
Definition: Likely.h:21
virtual bool prefetch(const IOPosBuffer *what, IOSize n)
Definition: XrdFile.cc:328
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
void addConnection(cms::Exception &)
Definition: XrdFile.cc:403
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:273
tuple conn
Definition: results_mgr.py:53
virtual void abort(void)
Definition: XrdFile.cc:211