00001 #include "Utilities/LStoreAdaptor/interface/LStoreFile.h"
00002 #include "FWCore/Utilities/interface/Exception.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 #include <cassert>
00005 #include <vector>
00006 #include <unistd.h>
00007 #include <fcntl.h>
00008 #include <pthread.h>
00009 #include <dlfcn.h>
00010 #include <iostream>
00011 #include <string.h>
00012
00013
00014
00015
00016 pthread_mutex_t LStoreFile::m_dlopen_lock = PTHREAD_MUTEX_INITIALIZER;
00017
00018 LStoreFile::LStoreFile (void)
00019 : m_fd (0),
00020 m_close (false),
00021 m_name(),
00022 m_library_handle(0),
00023 m_is_loaded(false),
00024 redd_init(0),
00025 redd_read(0),
00026 redd_close(0),
00027 redd_lseek(0),
00028 redd_open(0),
00029 redd_write(0),
00030 redd_term(0),
00031 redd_errno(0),
00032 redd_strerror(0)
00033 {
00034 loadLibrary();
00035 }
00036
00037 LStoreFile::LStoreFile (void * fd)
00038 : m_fd (fd),
00039 m_close (true),
00040 m_name(),
00041 m_library_handle(0),
00042 m_is_loaded(false),
00043 redd_init(0),
00044 redd_read(0),
00045 redd_close(0),
00046 redd_lseek(0),
00047 redd_open(0),
00048 redd_write(0),
00049 redd_term(0),
00050 redd_errno(0),
00051 redd_strerror(0)
00052 {
00053 loadLibrary();
00054 }
00055
00056 LStoreFile::LStoreFile (const char *name,
00057 int flags ,
00058 int perms )
00059 : m_fd (NULL),
00060 m_close (false),
00061 m_is_loaded(false)
00062 { loadLibrary();
00063 open (name, flags, perms); }
00064
00065 LStoreFile::LStoreFile (const std::string &name,
00066 int flags ,
00067 int perms )
00068 : m_fd (NULL),
00069 m_close (false),
00070 m_is_loaded(false)
00071 { loadLibrary();
00072 open (name.c_str (), flags, perms); }
00073
00074 LStoreFile::~LStoreFile (void)
00075 {
00076 if (m_close)
00077 edm::LogError("LStoreFileError")
00078 << "Destructor called on LStore file '" << m_name
00079 << "' but the file is still open";
00080 closeLibrary();
00081 }
00082
00083
00084
00085
00086
00087 #define REDD_LOAD_SYMBOL( NAME, TYPE ) dlerror();\
00088 NAME = reinterpret_cast<TYPE>(reinterpret_cast<size_t>( \
00089 dlsym(m_library_handle, #NAME))); \
00090 if ( (retval = dlerror()) ) {\
00091 throw cms::Exception("LStoreFile::loadLibrary()") <<\
00092 "Failed to load dlsym LStore library: " << retval;\
00093 }\
00094 if ( NAME == NULL) {\
00095 throw cms::Exception("LStoreFile::loadLibrary()") <<\
00096 "Got a null pointer back from dlsym()\n";\
00097 }
00098
00099 void LStoreFile::loadLibrary() {
00100 edm::LogError("LStoreFile::loadLibrary()") << "Loading library\n";
00101 LStoreFile::MutexWrapper lockObj( & this->m_dlopen_lock );
00102
00103
00104
00105
00106
00107
00108
00109 m_library_handle =
00110 dlopen("libreddnet.so", RTLD_LAZY);
00111 if (m_library_handle == NULL) {
00112 throw cms::Exception("LStoreFile::loadLibrary()")
00113 << "Can't dlopen() LStore libraries: " << dlerror();
00114 }
00115
00116 char * retval = NULL;
00117
00118 REDD_LOAD_SYMBOL( redd_init, int32_t(*)());
00119 REDD_LOAD_SYMBOL( redd_read, int64_t(*)(void *, char*, int64_t));
00120 REDD_LOAD_SYMBOL( redd_lseek, int64_t(*)(void*, int64_t, uint32_t));
00121 REDD_LOAD_SYMBOL( redd_open, void*(*)(const char*,int,int));
00122 REDD_LOAD_SYMBOL( redd_write, int64_t(*)(void *, const char *, int64_t));
00123 REDD_LOAD_SYMBOL( redd_term, int32_t(*)());
00124 REDD_LOAD_SYMBOL( redd_errno, int32_t(*)());
00125 REDD_LOAD_SYMBOL( redd_strerror, const std::string & (*)());
00126
00127 if ( (*redd_init)() ) {
00128 throw cms::Exception("LStoreFile::loadLibrary()")
00129 << "Error in redd_init: " << (*redd_strerror)();
00130 }
00131 m_is_loaded = true;
00132
00133 }
00134
00135 void LStoreFile::closeLibrary() {
00136 try {
00137 LStoreFile::MutexWrapper lockObj( & this->m_dlopen_lock );
00138
00139
00140
00141
00142
00143 if ( m_is_loaded ) {
00144 if ( (*redd_term)() ) {
00145 throw cms::Exception("LStoreFile::closeLibrary()")
00146 << "Error in redd_term: " << (*redd_strerror)();
00147 }
00148 }
00149 if ( m_library_handle != NULL ) {
00150 if ( dlclose( m_library_handle ) ) {
00151 throw cms::Exception("LStoreFile::closeLibrary()")
00152 << "Error on dlclose(): " << dlerror();
00153 }
00154 }
00155 } catch (cms::Exception & e) {
00156 edm::LogError("LStoreFileError")
00157 << "LStoreFile had an error in its destructor: " << e;
00158 }
00159 m_is_loaded = false;
00160 }
00161
00162
00164 void
00165 LStoreFile::create (const char *name,
00166 bool exclusive ,
00167 int perms )
00168 {
00169 open (name,
00170 (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00171 | (exclusive ? IOFlags::OpenExclusive : 0)),
00172 perms);
00173 }
00174
00175 void
00176 LStoreFile::create (const std::string &name,
00177 bool exclusive ,
00178 int perms )
00179 {
00180 open (name.c_str (),
00181 (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00182 | (exclusive ? IOFlags::OpenExclusive : 0)),
00183 perms);
00184 }
00185
00186 void
00187 LStoreFile::open (const std::string &name,
00188 int flags ,
00189 int perms )
00190 { open (name.c_str (), flags, perms); }
00191
00192 void
00193 LStoreFile::open (const char *name,
00194 int flags ,
00195 int perms )
00196 {
00197
00198 if ((name == 0) || (*name == 0))
00199 throw cms::Exception("LStoreFile::open()")
00200 << "Cannot open a file without a name";
00201
00202 if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0)
00203 throw cms::Exception("LStoreFile::open()")
00204 << "Must open file '" << name << "' at least for read or write";
00205
00206
00207 if (m_fd != NULL && m_close)
00208 close ();
00209
00210
00211 int openflags = 0;
00212
00213 if ((flags & IOFlags::OpenRead) && (flags & IOFlags::OpenWrite))
00214 openflags |= O_RDWR;
00215 else if (flags & IOFlags::OpenRead)
00216 openflags |= O_RDONLY;
00217 else if (flags & IOFlags::OpenWrite)
00218 openflags |= O_WRONLY;
00219
00220 if (flags & IOFlags::OpenNonBlock)
00221 openflags |= O_NONBLOCK;
00222
00223 if (flags & IOFlags::OpenAppend)
00224 openflags |= O_APPEND;
00225
00226 if (flags & IOFlags::OpenCreate)
00227 openflags |= O_CREAT;
00228
00229 if (flags & IOFlags::OpenExclusive)
00230 openflags |= O_EXCL;
00231
00232 if (flags & IOFlags::OpenTruncate)
00233 openflags |= O_TRUNC;
00234
00235 void * newfd = NULL;
00236 if ((newfd = (*redd_open) (name, openflags, perms)) == NULL)
00237 throw cms::Exception("LStoreFile::open()")
00238 << "redd_open(name='" << name
00239 << "', flags=0x" << std::hex << openflags
00240 << ", permissions=0" << std::oct << perms << std::dec
00241 << ") => error '" << (*redd_strerror)()
00242 << "' (redd_errno=" << (*redd_errno)() << ")";
00243
00244 m_name = name;
00245 m_fd = newfd;
00246
00247 m_close = true;
00248
00249 edm::LogInfo("LStoreFileInfo") << "Opened " << m_name;
00250 }
00251
00252 void
00253 LStoreFile::close (void)
00254 {
00255 if (m_fd == NULL)
00256 {
00257 edm::LogError("LStoreFileError")
00258 << "LStoreFile::close(name='" << m_name
00259 << "') called but the file is not open";
00260 m_close = false;
00261 return;
00262 }
00263 edm::LogInfo("LStoreFile::close()") << "closing " << m_name << std::endl;
00264 if ((*redd_close) (m_fd) == -1)
00265 edm::LogWarning("LStoreFileWarning")
00266 << "redd_close(name='" << m_name
00267 << "') failed with error '" << (*redd_strerror) ()
00268 << "' (redd_errno=" << (*redd_errno)() << ")";
00269
00270 m_close = false;
00271 m_fd = NULL;
00272
00273
00274
00275 }
00276
00277 void
00278 LStoreFile::abort (void)
00279 {
00280 if (m_fd != NULL)
00281 (*redd_close) (m_fd);
00282
00283 m_close = false;
00284 m_fd = NULL;
00285 }
00286
00287
00288 IOSize
00289 LStoreFile::read (void *into, IOSize n)
00290 {
00291 IOSize done = 0;
00292 while (done < n)
00293 {
00294 ssize_t s = (*redd_read) (m_fd, (char *) into + done, n - done);
00295 if (s == -1)
00296 throw cms::Exception("LStoreFile::read()")
00297 << "redd_read(name='" << m_name << "', n=" << (n-done)
00298 << ") failed with error '" << (*redd_strerror)()
00299 << "' (redd_errno=" << (*redd_errno)() << ")";
00300 done += s;
00301 }
00302 return done;
00303 }
00304
00305 IOSize
00306 LStoreFile::write (const void *from, IOSize n)
00307 {
00308 IOSize done = 0;
00309 while (done < n)
00310 {
00311 ssize_t s = (*redd_write) (m_fd, (const char *) from + done, n - done);
00312 if (s == -1)
00313 throw cms::Exception("LStoreFile::write()")
00314 << "redd_write(name='" << m_name << "', n=" << (n-done)
00315 << ") failed with error '" << (*redd_strerror)()
00316 << "' (redd_errno=" << (*redd_errno)() << ")";
00317 done += s;
00318 }
00319
00320 return done;
00321 }
00325 IOOffset
00326 LStoreFile::position (IOOffset offset, Relative whence )
00327 {
00328 if (m_fd == NULL)
00329 throw cms::Exception("LStoreFile::position()")
00330 << "LStoreFile::position() called on a closed file";
00331 if (whence != CURRENT && whence != SET && whence != END)
00332 throw cms::Exception("LStoreFile::position()")
00333 << "LStoreFile::position() called with incorrect 'whence' parameter";
00334
00335 IOOffset result;
00336 uint32_t mywhence = (whence == SET ? SEEK_SET
00337 : whence == CURRENT ? SEEK_CUR
00338 : SEEK_END);
00339 if ((result = (*redd_lseek) (m_fd, (off_t) offset, (uint32_t)mywhence)) == -1)
00340 throw cms::Exception("LStoreFile::position()")
00341 << "redd_lseek64(name='" << m_name << "', offset=" << offset
00342 << ", whence=" << mywhence << ") failed with error '"
00343 << (*redd_strerror) () << "' (redd_errno=" << (*redd_errno)() << ")";
00344 return result;
00345 }
00346
00347 void
00348 LStoreFile::resize (IOOffset )
00349 {
00350 throw cms::Exception("LStoreFile::resize()")
00351 << "LStoreFile::resize(name='" << m_name << "') not implemented";
00352 }
00353
00354
00356
00357 LStoreFile::MutexWrapper::MutexWrapper( pthread_mutex_t * target )
00358 {
00359 m_lock = target;
00360 pthread_mutex_lock( m_lock );
00361 }
00362
00363 LStoreFile::MutexWrapper::~MutexWrapper()
00364 {
00365 int retval;
00366 if ( (retval = pthread_mutex_unlock( m_lock )) ) {
00367
00368
00369
00370
00371
00372
00373 char buf[1024];
00374 edm::LogError("LStoreFileError")
00375 << "LStoreFile couldn't unlock a mutex. Not good."
00376 << strerror_r( retval, buf, 1024 );
00377 }
00378 }
00379