CMS 3D CMS Logo

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