CMS 3D CMS Logo

LStoreFile.cc
Go to the documentation of this file.
4 #include <cassert>
5 #include <vector>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <pthread.h>
9 #include <dlfcn.h>
10 #include <iostream>
11 #include <cstring>
12 
13 
14 
15 // dlsym isn't reentrant, need a locak around it
16 pthread_mutex_t LStoreFile::m_dlopen_lock = PTHREAD_MUTEX_INITIALIZER;
17 
19  : m_fd (nullptr),
20  m_close (false),
21  m_name(),
22  m_library_handle(nullptr),
23  m_is_loaded(false),
24  redd_init(nullptr),
25  redd_read(nullptr),
26  redd_close(nullptr),
27  redd_lseek(nullptr),
28  redd_open(nullptr),
29  redd_write(nullptr),
30  redd_term(nullptr),
31  redd_errno(nullptr),
32  redd_strerror(nullptr)
33 {
34  loadLibrary();
35 }
36 
38  : m_fd (fd),
39  m_close (true),
40  m_name(),
52 {
53  loadLibrary();
54 }
55 
57  int flags /* = IOFlags::OpenRead */,
58  int perms /* = 066 */ )
59  : m_fd (nullptr),
60  m_close (false),
62 { loadLibrary();
63  open (name, flags, perms); }
64 
66  int flags /* = IOFlags::OpenRead*/,
67  int perms /* = 066 */)
68  : m_fd (nullptr),
69  m_close (false),
71 { loadLibrary();
72  open (name.c_str (), flags, perms); }
73 
75 {
76  if (m_close)
77  edm::LogError("LStoreFileError")
78  << "Destructor called on LStore file '" << m_name
79  << "' but the file is still open";
80  closeLibrary();
81 }
82 
83 
84 // Helper macro to perform dlsym()
85 // Double cast is supposed to be more compliant
86 // otherwise, GCC complains with the pointer conversion
87 #define REDD_LOAD_SYMBOL( NAME, TYPE ) dlerror();\
88  NAME = reinterpret_cast<TYPE>(reinterpret_cast<size_t>( \
89  dlsym(m_library_handle, #NAME))); \
90  if ( (retval = dlerror()) ) {\
91  throw cms::Exception("LStoreFile::loadLibrary()") <<\
92  "Failed to load dlsym LStore library: " << retval;\
93  }\
94  if ( NAME == NULL) {\
95  throw cms::Exception("LStoreFile::loadLibrary()") <<\
96  "Got a null pointer back from dlsym()\n";\
97  }
98 
100  edm::LogError("LStoreFile::loadLibrary()") << "Loading library\n";
101  LStoreFile::MutexWrapper lockObj( & this->m_dlopen_lock );
102  // until ACCRE removes the java dependency from their client libs,
103  // we'll dlopen() them so they don't need to be brought along with cmssw
104  // if you're running LStore at your site, you will have the libs anyway
105  // TODO add wrappers to make this work in OSX as well (CMSSW's getting ported?)
106  // TODO should be easy, just need to know the "proper" way to do #if OSX
107  // -Melo
108 
110  dlopen("libreddnet.so", RTLD_LAZY);
111  if (m_library_handle == nullptr) {
112  throw cms::Exception("LStoreFile::loadLibrary()")
113  << "Can't dlopen() LStore libraries: " << dlerror();
114  }
115 
116  char * retval = nullptr;
117  // Explicitly state the size of these values, keeps weird 64/32 bit stuff away
118  REDD_LOAD_SYMBOL( redd_init, int32_t(*)());
119  REDD_LOAD_SYMBOL( redd_read, int64_t(*)(void *, char*, int64_t));
120  REDD_LOAD_SYMBOL( redd_lseek, int64_t(*)(void*, int64_t, uint32_t));
121  REDD_LOAD_SYMBOL( redd_open, void*(*)(const char*,int,int));
122  REDD_LOAD_SYMBOL( redd_write, int64_t(*)(void *, const char *, int64_t));
123  REDD_LOAD_SYMBOL( redd_term, int32_t(*)());
124  REDD_LOAD_SYMBOL( redd_errno, int32_t(*)());
125  REDD_LOAD_SYMBOL( redd_strerror, const std::string & (*)());
126 
127  if ( (*redd_init)() ) {
128  throw cms::Exception("LStoreFile::loadLibrary()")
129  << "Error in redd_init: " << (*redd_strerror)();
130  }
131  m_is_loaded = true;
132 
133 }
134 
136  try {
137  LStoreFile::MutexWrapper lockObj( & this->m_dlopen_lock );
138 
139  // What is the correct idiom for propagating error messages
140  // in functions that are exclusively called in destructors?
141  // Seriously. I have no idea
142  // melo
143  if ( m_is_loaded ) {
144  if ( (*redd_term)() ) {
145  throw cms::Exception("LStoreFile::closeLibrary()")
146  << "Error in redd_term: " << (*redd_strerror)();
147  }
148  }
149  if ( m_library_handle != nullptr ) {
150  if ( dlclose( m_library_handle ) ) {
151  throw cms::Exception("LStoreFile::closeLibrary()")
152  << "Error on dlclose(): " << dlerror();
153  }
154  }
155  } catch (cms::Exception & e) {
156  edm::LogError("LStoreFileError")
157  << "LStoreFile had an error in its destructor: " << e;
158  }
159  m_is_loaded = false;
160 }
161 
162 
164 void
166  bool exclusive /* = false */,
167  int perms /* = 066 */)
168 {
169  open (name,
171  | (exclusive ? IOFlags::OpenExclusive : 0)),
172  perms);
173 }
174 
175 void
177  bool exclusive /* = false */,
178  int perms /* = 066 */)
179 {
180  open (name.c_str (),
182  | (exclusive ? IOFlags::OpenExclusive : 0)),
183  perms);
184 }
185 
186 void
188  int flags /* = IOFlags::OpenRead */,
189  int perms /* = 066 */)
190 { open (name.c_str (), flags, perms); }
191 
192 void
193 LStoreFile::open (const char *name,
194  int flags /* = IOFlags::OpenRead */,
195  int perms /* = 066 */)
196 {
197  // Actual open
198  if ((name == nullptr) || (*name == 0))
199  throw cms::Exception("LStoreFile::open()")
200  << "Cannot open a file without a name";
201 
202  if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0)
203  throw cms::Exception("LStoreFile::open()")
204  << "Must open file '" << name << "' at least for read or write";
205 
206  // If I am already open, close old file first
207  if (m_fd != nullptr && m_close)
208  close ();
209 
210  // Translate our flags to system flags
211  int openflags = 0;
212 
213  if ((flags & IOFlags::OpenRead) && (flags & IOFlags::OpenWrite))
214  openflags |= O_RDWR;
215  else if (flags & IOFlags::OpenRead)
216  openflags |= O_RDONLY;
217  else if (flags & IOFlags::OpenWrite)
218  openflags |= O_WRONLY;
219 
220  if (flags & IOFlags::OpenNonBlock)
221  openflags |= O_NONBLOCK;
222 
223  if (flags & IOFlags::OpenAppend)
224  openflags |= O_APPEND;
225 
226  if (flags & IOFlags::OpenCreate)
227  openflags |= O_CREAT;
228 
229  if (flags & IOFlags::OpenExclusive)
230  openflags |= O_EXCL;
231 
232  if (flags & IOFlags::OpenTruncate)
233  openflags |= O_TRUNC;
234 
235  void * newfd = nullptr;
236  if ((newfd = (*redd_open) (name, openflags, perms)) == nullptr)
237  throw cms::Exception("LStoreFile::open()")
238  << "redd_open(name='" << name
239  << "', flags=0x" << std::hex << openflags
240  << ", permissions=0" << std::oct << perms << std::dec
241  << ") => error '" << (*redd_strerror)()
242  << "' (redd_errno=" << (*redd_errno)() << ")";
243 
244  m_name = name;
245  m_fd = newfd;
246 
247  m_close = true;
248 
249  edm::LogInfo("LStoreFileInfo") << "Opened " << m_name;
250 }
251 
252 void
254 {
255  if (m_fd == nullptr)
256  {
257  edm::LogError("LStoreFileError")
258  << "LStoreFile::close(name='" << m_name
259  << "') called but the file is not open";
260  m_close = false;
261  return;
262  }
263  edm::LogInfo("LStoreFile::close()") << "closing " << m_name << std::endl;
264  if ((*redd_close) (m_fd) == -1)
265  edm::LogWarning("LStoreFileWarning")
266  << "redd_close(name='" << m_name
267  << "') failed with error '" << (*redd_strerror) ()
268  << "' (redd_errno=" << (*redd_errno)() << ")";
269 
270  m_close = false;
271  m_fd = nullptr;
272 
273  // Caused hang. Will be added back after problem is fixed.
274  // edm::LogInfo("LStoreFileInfo") << "Closed " << m_name;
275 }
276 
277 void
279 {
280  if (m_fd != nullptr)
281  (*redd_close) (m_fd);
282 
283  m_close = false;
284  m_fd = nullptr;
285 }
286 
287 
288 IOSize
289 LStoreFile::read (void *into, IOSize n)
290 {
291  IOSize done = 0;
292  while (done < n)
293  {
294  ssize_t s = (*redd_read) (m_fd, (char *) into + done, n - done);
295  if (s == -1)
296  throw cms::Exception("LStoreFile::read()")
297  << "redd_read(name='" << m_name << "', n=" << (n-done)
298  << ") failed with error '" << (*redd_strerror)()
299  << "' (redd_errno=" << (*redd_errno)() << ")";
300  done += s;
301  }
302  return done;
303 }
304 
305 IOSize
306 LStoreFile::write (const void *from, IOSize n)
307 {
308  IOSize done = 0;
309  while (done < n)
310  {
311  ssize_t s = (*redd_write) (m_fd, (const char *) from + done, n - done);
312  if (s == -1)
313  throw cms::Exception("LStoreFile::write()")
314  << "redd_write(name='" << m_name << "', n=" << (n-done)
315  << ") failed with error '" << (*redd_strerror)()
316  << "' (redd_errno=" << (*redd_errno)() << ")";
317  done += s;
318  }
319 
320  return done;
321 }
325 IOOffset
327 {
328  if (m_fd == nullptr)
329  throw cms::Exception("LStoreFile::position()")
330  << "LStoreFile::position() called on a closed file";
331  if (whence != CURRENT && whence != SET && whence != END)
332  throw cms::Exception("LStoreFile::position()")
333  << "LStoreFile::position() called with incorrect 'whence' parameter";
334 
336  uint32_t mywhence = (whence == SET ? SEEK_SET
337  : whence == CURRENT ? SEEK_CUR
338  : SEEK_END);
339  if ((result = (*redd_lseek) (m_fd, (off_t) offset, (uint32_t)mywhence)) == -1)
340  throw cms::Exception("LStoreFile::position()")
341  << "redd_lseek64(name='" << m_name << "', offset=" << offset
342  << ", whence=" << mywhence << ") failed with error '"
343  << (*redd_strerror) () << "' (redd_errno=" << (*redd_errno)() << ")";
344  return result;
345 }
346 
347 void
349 {
350  throw cms::Exception("LStoreFile::resize()")
351  << "LStoreFile::resize(name='" << m_name << "') not implemented";
352 }
353 
354 
356 
358 {
359  m_lock = target;
360  pthread_mutex_lock( m_lock ); // never fails
361 }
362 
364 {
365  int retval;
366  if ( (retval = pthread_mutex_unlock( m_lock )) ) {
367  // congrats. pthread_mutex_lock failed and we're in a destructor
368  // I don't know what to do here
369  // Then again, if the mutex is jammed, things are already boned
370  // Cry for a second, then continue with life, I guess
371  // melo
372 
373  char buf[1024];
374  edm::LogError("LStoreFileError")
375  << "LStoreFile couldn't unlock a mutex. Not good."
376  << strerror_r( retval, buf, 1024 );
377  }
378 }
379 
void loadLibrary()
Definition: LStoreFile.cc:99
int32_t(* redd_errno)()
Definition: LStoreFile.h:76
void * m_library_handle
Definition: LStoreFile.h:63
int64_t(* redd_lseek)(void *, int64_t, uint32_t)
Definition: LStoreFile.h:72
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
#define nullptr
std::string m_name
Definition: LStoreFile.h:62
void close(void) override
Definition: LStoreFile.cc:253
int32_t(* redd_init)()
Definition: LStoreFile.h:69
Relative
Definition: Storage.h:23
int32_t(* redd_term)()
Definition: LStoreFile.h:75
bool m_close
Definition: LStoreFile.h:61
void * m_fd
Definition: LStoreFile.h:60
int64_t(* redd_write)(void *, const char *, int64_t)
Definition: LStoreFile.h:74
MutexWrapper(pthread_mutex_t *lock)
Definition: LStoreFile.cc:357
void *(* redd_open)(const char *, int32_t, int32_t)
Definition: LStoreFile.h:73
virtual IOOffset position(void) const
Definition: Storage.cc:95
void resize(IOOffset size) override
Definition: LStoreFile.cc:348
int read(void)
Definition: IOInput.cc:54
virtual void open(const char *name, int flags=IOFlags::OpenRead, int perms=0666)
Definition: LStoreFile.cc:193
virtual void abort(void)
Definition: LStoreFile.cc:278
void closeLibrary()
Definition: LStoreFile.cc:135
#define REDD_LOAD_SYMBOL(NAME, TYPE)
Definition: LStoreFile.cc:87
int64_t IOOffset
Definition: IOTypes.h:19
bool m_is_loaded
Definition: LStoreFile.h:64
const std::string &(* redd_strerror)()
Definition: LStoreFile.h:77
int32_t(* redd_close)(void *)
Definition: LStoreFile.h:71
int64_t(* redd_read)(void *, char *, int64_t)
Definition: LStoreFile.h:70
LStoreFile(void)
Definition: LStoreFile.cc:18
static pthread_mutex_t m_dlopen_lock
Definition: LStoreFile.h:50
virtual void create(const char *name, bool exclusive=false, int perms=0666)
Definition: LStoreFile.cc:165
#define O_NONBLOCK
Definition: SysFile.h:21
size_t IOSize
Definition: IOTypes.h:14
IOSize write(const void *from, IOSize n) override
Definition: LStoreFile.cc:306
~LStoreFile(void) override
Definition: LStoreFile.cc:74