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