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