00001 #include "Utilities/XrdAdaptor/src/XrdFile.h"
00002 #include "FWCore/Utilities/interface/Exception.h"
00003 #include "FWCore/Utilities/interface/EDMException.h"
00004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00005 #include <vector>
00006
00007 XrdFile::XrdFile (void)
00008 : m_client (0),
00009 m_offset (0),
00010 m_close (false)
00011 {}
00012
00013 XrdFile::XrdFile (const char *name,
00014 int flags ,
00015 int perms )
00016 : m_client (0),
00017 m_offset (0),
00018 m_close (false)
00019 { open (name, flags, perms); }
00020
00021 XrdFile::XrdFile (const std::string &name,
00022 int flags ,
00023 int perms )
00024 : m_client (0),
00025 m_offset (0),
00026 m_close (false)
00027 { open (name.c_str (), flags, perms); }
00028
00029 XrdFile::~XrdFile (void)
00030 {
00031 if (m_close)
00032 edm::LogError("XrdFileError")
00033 << "Destructor called on XROOTD file '" << m_name
00034 << "' but the file is still open";
00035 }
00036
00038 void
00039 XrdFile::create (const char *name,
00040 bool exclusive ,
00041 int perms )
00042 {
00043 open (name,
00044 (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00045 | (exclusive ? IOFlags::OpenExclusive : 0)),
00046 perms);
00047 }
00048
00049 void
00050 XrdFile::create (const std::string &name,
00051 bool exclusive ,
00052 int perms )
00053 {
00054 open (name.c_str (),
00055 (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00056 | (exclusive ? IOFlags::OpenExclusive : 0)),
00057 perms);
00058 }
00059
00060 void
00061 XrdFile::open (const std::string &name,
00062 int flags ,
00063 int perms )
00064 { open (name.c_str (), flags, perms); }
00065
00066 void
00067 XrdFile::open (const char *name,
00068 int flags ,
00069 int perms )
00070 {
00071 m_name = name;
00072
00073
00074 if ((name == 0) || (*name == 0)) {
00075 edm::Exception ex(edm::errors::FileOpenError);
00076 ex << "Cannot open a file without a name";
00077 ex.addContext("Calling XrdFile::open()");
00078 throw ex;
00079 }
00080 if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0) {
00081 edm::Exception ex(edm::errors::FileOpenError);
00082 ex << "Must open file '" << name << "' at least for read or write";
00083 ex.addContext("Calling XrdFile::open()");
00084 throw ex;
00085 }
00086
00087 if (m_client && m_close)
00088 close();
00089 else
00090 abort();
00091
00092
00093 int openflags = 0;
00094
00095 if (flags & IOFlags::OpenWrite)
00096 openflags |= kXR_open_updt;
00097 else if (flags & IOFlags::OpenRead)
00098 openflags |= kXR_open_read;
00099
00100 if (flags & IOFlags::OpenAppend) {
00101 edm::Exception ex(edm::errors::FileOpenError);
00102 ex << "Opening file '" << name << "' in append mode not supported";
00103 ex.addContext("Calling XrdFile::open()");
00104 throw ex;
00105 }
00106
00107 if (flags & IOFlags::OpenCreate)
00108 {
00109 if (! (flags & IOFlags::OpenExclusive))
00110 openflags |= kXR_delete;
00111 openflags |= kXR_new;
00112 openflags |= kXR_mkpath;
00113 }
00114
00115 if ((flags & IOFlags::OpenTruncate) && (flags & IOFlags::OpenWrite))
00116 openflags |= kXR_delete;
00117
00118 m_client = new XrdClient(name);
00119 if (! m_client->Open(perms, openflags)
00120 || m_client->LastServerResp()->status != kXR_ok) {
00121 edm::Exception ex(edm::errors::FileOpenError);
00122 ex << "XrdClient::Open(name='" << name
00123 << "', flags=0x" << std::hex << openflags
00124 << ", permissions=0" << std::oct << perms << std::dec
00125 << ") => error '" << m_client->LastServerError()->errmsg
00126 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00127 ex.addContext("Calling XrdFile::open()");
00128 throw ex;
00129 }
00130 if (! m_client->Stat(&m_stat)) {
00131 edm::Exception ex(edm::errors::FileOpenError);
00132 ex << "XrdClient::Stat(name='" << name
00133 << ") => error '" << m_client->LastServerError()->errmsg
00134 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00135 ex.addContext("Calling XrdFile::open()");
00136 throw ex;
00137 }
00138 m_offset = 0;
00139 m_close = true;
00140 edm::LogInfo("XrdFileInfo") << "Opened " << m_name;
00141 }
00142
00143 void
00144 XrdFile::close (void)
00145 {
00146 if (! m_client)
00147 {
00148 edm::LogError("XrdFileError")
00149 << "XrdFile::close(name='" << m_name
00150 << "') called but the file is not open";
00151 m_close = false;
00152 return;
00153 }
00154
00155 if (! m_client->Close())
00156 edm::LogWarning("XrdFileWarning")
00157 << "XrdFile::close(name='" << m_name
00158 << "') failed with error '" << m_client->LastServerError()->errmsg
00159 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00160 delete m_client;
00161 m_client = 0;
00162
00163 m_close = false;
00164 m_offset = 0;
00165 memset(&m_stat, 0, sizeof (m_stat));
00166 edm::LogInfo("XrdFileInfo") << "Closed " << m_name;
00167 }
00168
00169 void
00170 XrdFile::abort (void)
00171 {
00172 delete m_client;
00173 m_client = 0;
00174 m_close = false;
00175 m_offset = 0;
00176 memset(&m_stat, 0, sizeof (m_stat));
00177 }
00178
00180 IOSize
00181 XrdFile::read (void *into, IOSize n)
00182 {
00183 if (n > 0x7fffffff) {
00184 edm::Exception ex(edm::errors::FileReadError);
00185 ex << "XrdFile::read(name='" << m_name << "', n=" << n
00186 << ") too many bytes, limit is 0x7fffffff";
00187 ex.addContext("Calling XrdFile::read()");
00188 throw ex;
00189 }
00190 int s = m_client->Read(into, m_offset, n);
00191 if (s < 0) {
00192 edm::Exception ex(edm::errors::FileReadError);
00193 ex << "XrdClient::Read(name='" << m_name
00194 << "', offset=" << m_offset << ", n=" << n
00195 << ") failed with error '" << m_client->LastServerError()->errmsg
00196 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00197 ex.addContext("Calling XrdFile::read()");
00198 throw ex;
00199 }
00200 m_offset += s;
00201 return s;
00202 }
00203
00204 IOSize
00205 XrdFile::read (void *into, IOSize n, IOOffset pos)
00206 {
00207 if (n > 0x7fffffff) {
00208 edm::Exception ex(edm::errors::FileReadError);
00209 ex << "XrdFile::read(name='" << m_name << "', n=" << n
00210 << ") exceeds read size limit 0x7fffffff";
00211 ex.addContext("Calling XrdFile::read()");
00212 throw ex;
00213 }
00214 int s = m_client->Read(into, pos, n);
00215 if (s < 0) {
00216 edm::Exception ex(edm::errors::FileReadError);
00217 ex << "XrdClient::Read(name='" << m_name
00218 << "', offset=" << m_offset << ", n=" << n
00219 << ") failed with error '" << m_client->LastServerError()->errmsg
00220 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00221 ex.addContext("Calling XrdFile::read()");
00222 throw ex;
00223 }
00224 return s;
00225 }
00226
00227 IOSize
00228 XrdFile::readv (IOBuffer *into, IOSize n)
00229 {
00230
00231
00232
00233
00234
00235
00236
00237 IOOffset pos = m_offset;
00238 std::vector<long long> offsets (n);
00239 std::vector<int> lengths (n);
00240 for (IOSize i = 0; i < n; ++i)
00241 {
00242 IOSize len = into[i].size();
00243 if (len > 0x7fffffff) {
00244 edm::Exception ex(edm::errors::FileReadError);
00245 ex << "XrdFile::readv(name='" << m_name << "')[" << i
00246 << "].size=" << len << " exceeds read size limit 0x7fffffff";
00247 ex.addContext("Calling XrdFile::readv()");
00248 throw ex;
00249 }
00250 offsets[i] = pos;
00251 lengths[i] = len;
00252 pos += len;
00253 }
00254
00255
00256 if (m_client->ReadV(0, &offsets[0], &lengths[0], n) < 0) {
00257 edm::Exception ex(edm::errors::FileReadError);
00258 ex << "XrdClient::ReadV(name='" << m_name
00259 << "') failed with error '" << m_client->LastServerError()->errmsg
00260 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00261 ex.addContext("Calling XrdFile::readv()");
00262 throw ex;
00263 }
00264
00265
00266 IOSize total = 0;
00267 for (IOSize i = 0; i < n; ++i)
00268 {
00269 int s = m_client->Read(into[i].data(), offsets[i], lengths[i]);
00270 if (s < 0)
00271 {
00272 if (i > 0)
00273 break;
00274 edm::Exception ex(edm::errors::FileReadError);
00275 ex << "XrdClient::Read(name='" << m_name
00276 << "', offset=" << offsets[i] << ", n=" << lengths[i]
00277 << ") failed with error '" << m_client->LastServerError()->errmsg
00278 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00279 ex.addContext("Calling XrdFile::readv()");
00280 throw ex;
00281 }
00282 total += s;
00283 m_offset += s;
00284 }
00285
00286 return total;
00287 }
00288
00289 IOSize
00290 XrdFile::readv (IOPosBuffer *into, IOSize n)
00291 {
00292
00293 std::vector<long long> offsets (n);
00294 std::vector<int> lengths (n);
00295 for (IOSize i = 0; i < n; ++i)
00296 {
00297 IOSize len = into[i].size();
00298 if (len > 0x7fffffff) {
00299 edm::Exception ex(edm::errors::FileReadError);
00300 ex << "XrdFile::readv(name='" << m_name << "')[" << i
00301 << "].size=" << len << " exceeds read size limit 0x7fffffff";
00302 ex.addContext("Calling XrdFile::readv()");
00303 throw ex;
00304 }
00305 offsets[i] = into[i].offset();
00306 lengths[i] = len;
00307 }
00308
00309
00310 if (m_client->ReadV(0, &offsets[0], &lengths[0], n) < 0) {
00311 edm::Exception ex(edm::errors::FileReadError);
00312 ex << "XrdClient::ReadV(name='" << m_name
00313 << "') failed with error '" << m_client->LastServerError()->errmsg
00314 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00315 ex.addContext("Calling XrdFile::readv()");
00316 throw ex;
00317 }
00318
00319 IOSize total = 0;
00320 for (IOSize i = 0; i < n; ++i)
00321 {
00322 int s = m_client->Read(into[i].data(), offsets[i], lengths[i]);
00323 if (s < 0)
00324 {
00325 if (i > 0)
00326 break;
00327 edm::Exception ex(edm::errors::FileReadError);
00328 ex << "XrdClient::Read(name='" << m_name
00329 << "', offset=" << offsets[i] << ", n=" << lengths[i]
00330 << ") failed with error '" << m_client->LastServerError()->errmsg
00331 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00332 ex.addContext("Calling XrdFile::readv()");
00333 throw ex;
00334 }
00335 total += s;
00336 }
00337
00338 return total;
00339 }
00340
00341 IOSize
00342 XrdFile::write (const void *from, IOSize n)
00343 {
00344 if (n > 0x7fffffff) {
00345 cms::Exception ex("FileWriteError");
00346 ex << "XrdFile::write(name='" << m_name << "', n=" << n
00347 << ") too many bytes, limit is 0x7fffffff";
00348 ex.addContext("Calling XrdFile::write()");
00349 throw ex;
00350 }
00351 ssize_t s = m_client->Write(from, m_offset, n);
00352 if (s < 0) {
00353 cms::Exception ex("FileWriteError");
00354 ex << "XrdFile::write(name='" << m_name << "', n=" << n
00355 << ") failed with error '" << m_client->LastServerError()->errmsg
00356 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00357 ex.addContext("Calling XrdFile::write()");
00358 throw ex;
00359 }
00360 m_offset += s;
00361 if (m_offset > m_stat.size)
00362 m_stat.size = m_offset;
00363
00364 return s;
00365 }
00366
00367 IOSize
00368 XrdFile::write (const void *from, IOSize n, IOOffset pos)
00369 {
00370 if (n > 0x7fffffff) {
00371 cms::Exception ex("FileWriteError");
00372 ex << "XrdFile::write(name='" << m_name << "', n=" << n
00373 << ") too many bytes, limit is 0x7fffffff";
00374 ex.addContext("Calling XrdFile::write()");
00375 throw ex;
00376 }
00377 ssize_t s = m_client->Write(from, pos, n);
00378 if (s < 0) {
00379 cms::Exception ex("FileWriteError");
00380 ex << "XrdFile::write(name='" << m_name << "', n=" << n
00381 << ") failed with error '" << m_client->LastServerError()->errmsg
00382 << "' (errno=" << m_client->LastServerError()->errnum << ")";
00383 ex.addContext("Calling XrdFile::write()");
00384 throw ex;
00385 }
00386 if (pos + s > m_stat.size)
00387 m_stat.size = pos + s;
00388
00389 return s;
00390 }
00391
00392 bool
00393 XrdFile::prefetch (const IOPosBuffer *what, IOSize n)
00394 {
00395 XReqErrorType r = kOK;
00396 for (IOSize i = 0; i < n && r == kOK; ++i)
00397 r = m_client->Read_Async(what[i].offset(), what[i].size());
00398 return r == kOK;
00399 }
00400
00404 IOOffset
00405 XrdFile::position (IOOffset offset, Relative whence )
00406 {
00407 if (! m_client) {
00408 cms::Exception ex("FilePositionError");
00409 ex << "XrdFile::position() called on a closed file";
00410 ex.addContext("Calling XrdFile::position()");
00411 throw ex;
00412 }
00413 switch (whence)
00414 {
00415 case SET:
00416 m_offset = offset;
00417 break;
00418
00419 case CURRENT:
00420 m_offset += offset;
00421 break;
00422
00423 case END:
00424 m_offset = m_stat.size + offset;
00425 break;
00426
00427 default:
00428 cms::Exception ex("FilePositionError");
00429 ex << "XrdFile::position() called with incorrect 'whence' parameter";
00430 ex.addContext("Calling XrdFile::position()");
00431 throw ex;
00432 }
00433
00434 if (m_offset < 0)
00435 m_offset = 0;
00436 if (m_offset > m_stat.size)
00437 m_stat.size = m_offset;
00438
00439 return m_offset;
00440 }
00441
00442 void
00443 XrdFile::resize (IOOffset )
00444 {
00445 cms::Exception ex("FileResizeError");
00446 ex << "XrdFile::resize(name='" << m_name << "') not implemented";
00447 ex.addContext("Calling XrdFile::resize()");
00448 throw ex;
00449 }