CMS 3D CMS Logo

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