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