μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ProtocolMmap.cpp
Go to the documentation of this file.
1/*
2---------------------------------------------------------------------------
3
4 This file is part of uHAL.
5
6 uHAL is a hardware access library and programming framework
7 originally developed for upgrades of the Level-1 trigger of the CMS
8 experiment at CERN.
9
10 uHAL is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 uHAL is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with uHAL. If not, see <http://www.gnu.org/licenses/>.
22
23
24 Andrew Rose, Imperial College, London
25 email: awr01 <AT> imperial.ac.uk
26
27 Marc Magrans de Abril, CERN
28 email: marc.magrans.de.abril <AT> cern.ch
29
30 Tom Williams, Rutherford Appleton Laboratory, Oxfordshire
31 email: tom.williams <AT> cern.ch
32
33---------------------------------------------------------------------------
34*/
35
42#include "uhal/ProtocolMmap.hpp"
43
44
45#include <algorithm> // for min
46#include <assert.h>
47#include <chrono>
48#include <cstdlib>
49#include <fcntl.h>
50#include <iomanip> // for operator<<
51#include <iostream> // for operator<<
52#include <sys/file.h>
53#include <sys/mman.h>
54#include <sys/stat.h>
55#include <stdlib.h> // for size_t, free
56#include <string.h> // for memcpy
57#include <thread>
58#include <unistd.h>
59
60#include <boost/lexical_cast.hpp>
61#include <boost/date_time/posix_time/posix_time_types.hpp> // for time_dura...
62
64#include "uhal/grammars/URI.hpp" // for URI
65#include "uhal/log/LogLevels.hpp" // for BaseLogLevel
66#include "uhal/log/log_inserters.integer.hpp" // for Integer
67#include "uhal/log/log_inserters.quote.hpp" // for Quote
68#include "uhal/log/log.hpp"
69#include "uhal/Buffers.hpp"
71#include "uhal/SigBusGuard.hpp"
72
73
74namespace uhal {
75
76Mmap::File::File(const std::string& aPath, int aFlags) :
77 mPath(aPath),
78 mFd(-1),
79 mFlags(aFlags),
80 mLocked(false),
81 mOffset(0),
82 mMmapPtr(NULL),
83 mMmapIOPtr(NULL)
84{
85}
86
87
89{
90 close();
91}
92
93
94const std::string& Mmap::File::getPath() const
95{
96 return mPath;
97}
98
99
100void Mmap::File::setPath(const std::string& aPath)
101{
102 mPath = aPath;
103}
104
105
106void Mmap::File::setOffset(size_t aOffset)
107{
108 mOffset = aOffset;
109}
110
111
112// The default version of ipbus_transport_axi_if uses four IPBus
113// transport buffers, each with a 2^11-bit address space. In
114// addition, the first four 32-bit words in the IPBus transport
115// address space contain status information. This means the
116// corresponding memory memory map needs to allocate 2^15 + 16 bytes.
117#define MAP_SIZE (32*1024UL + 16UL)
118#define MAP_MASK (MAP_SIZE - 1)
119
120
122{
123 if (mFd != -1)
124 return;
125
126 mFd = ::open(mPath.c_str(), mFlags);
127 if ( mFd == -1 ) {
128 exception::MmapInitialisationError lExc;
129 log(lExc, "Failed to open device file ", Quote(mPath), "; errno=", Integer(errno), ", meaning ", Quote (strerror(errno)));
130 throw lExc;
131 }
132
133 const off_t lPageSize = sysconf(_SC_PAGESIZE);
134 const off_t lPageBaseAddr = (mOffset & ~(lPageSize-1));
135
136 mMmapPtr = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mFd, lPageBaseAddr);
137 mMmapIOPtr = static_cast<uint8_t*>(mMmapPtr) + (mOffset - lPageBaseAddr);
138
139 if (mMmapPtr == (void *)-1) {
140 exception::MmapInitialisationError lExc;
141 log(lExc, "Error occurred when mapping device file '" + mPath + "' to memory; errno=", Integer(errno), ", meaning ", Quote (strerror(errno)));
142 throw lExc;
143 }
144}
145
146
148{
149 if (mMmapPtr != NULL) {
150 if (munmap(mMmapPtr, MAP_SIZE) == -1)
151 log ( Error() , "mmap client for ", Quote(mPath), " encountered error when unmapping memory" );
152 else {
153 mMmapPtr = NULL;
154 mMmapIOPtr = NULL;
155 }
156 }
157
158 if (mFd != -1) {
159 int rc = ::close(mFd);
160 mFd = -1;
161 if (rc == -1)
162 log (Error(), "Failed to close file ", Quote(mPath), "; errno=", Integer(errno), ", meaning ", Quote (strerror(errno)));
163 }
164}
165
166
167void Mmap::File::read(const uint32_t aAddr, const uint32_t aNrWords, std::vector<uint32_t>& aValues)
168{
169 if (mFd == -1)
170 open();
171
172 if (4 * aAddr + 4 * aNrWords > size_t(MAP_SIZE)) {
173 exception::MmapInitialisationError lExc;
174 log(lExc, "Attempted to read beyond the end of mapped memory for device file '" + mPath + "' (reading ", Integer(4 * aNrWords), " bytes from address ", Integer(4 * aAddr), ", i.e. ", Integer(uint32_t(4 * aAddr + 4 * aNrWords - MAP_SIZE)), " bytes beyond end of ", Integer(uint32_t(MAP_SIZE)), " mapped bytes.");
175 throw lExc;
176 }
177
178 std::ostringstream lMessage;
179 lMessage << "SIGBUS received during " << 4*aNrWords << "-byte read @ 0x" << std::hex << 4*aAddr << " in " << mPath;
180 SigBusGuard lGuard;
181 lGuard.protect([&]{
182 uint8_t* lVirtAddr = static_cast<uint8_t*>(mMmapIOPtr) + off_t(4*aAddr);
183
184 for (size_t i=0; i<aNrWords; i++) {
185 aValues.push_back(*((uint32_t*) (lVirtAddr + 4 * i)));
186 }
187 }, lMessage.str());
188}
189
190
191void Mmap::File::write(const uint32_t aAddr, const std::vector<std::pair<const uint8_t*, size_t> >& aData)
192{
193 if (mFd == -1)
194 open();
195
196 size_t lNrBytes = 0;
197 for (size_t i = 0; i < aData.size(); i++)
198 lNrBytes += aData.at(i).second;
199
200 assert((lNrBytes % 4) == 0);
201
202 if (aAddr + lNrBytes > size_t(MAP_SIZE)) {
203 exception::MmapInitialisationError lExc;
204 log(lExc, "Attempted to write beyond the end of mapped memory for device file '" + mPath + "' (writing ", Integer(lNrBytes), " bytes at address ", Integer(aAddr), ", i.e. ", Integer(uint32_t(aAddr + lNrBytes - MAP_SIZE)), " bytes beyond end of ", Integer(uint32_t(MAP_SIZE)), " mapped bytes.");
205 throw lExc;
206 }
207
208 char *allocated = NULL;
209 posix_memalign((void **)&allocated, 4096/*alignment*/, lNrBytes + 4096);
210 if (allocated == NULL) {
211 exception::MmapCommunicationError lExc;
212 log(lExc, "Failed to allocate ", Integer(lNrBytes + 4096), " bytes in File::write/2 function");
213 throw lExc;
214 }
215
216 std::ostringstream lMessage;
217 lMessage << "SIGBUS received during " << lNrBytes << "-byte write @ 0x" << std::hex << aAddr << " in " << mPath;
218 SigBusGuard lGuard;
219 lGuard.protect([&]{
220 // data to write to register address
221 char* buffer = allocated;
222 size_t lNrBytesCopied = 0;
223 for (size_t i = 0; i < aData.size(); i++) {
224 memcpy(buffer + lNrBytesCopied, aData.at(i).first, aData.at(i).second);
225 lNrBytesCopied += aData.at(i).second;
226 }
227
228 lNrBytesCopied = 0;
229 while (lNrBytesCopied < lNrBytes) {
230 char* lSrcPtr = buffer + lNrBytesCopied;
231 char* lVirtAddr = static_cast<char*>(mMmapIOPtr) + aAddr + lNrBytesCopied;
232 if ((lNrBytes - lNrBytesCopied) >= 8) {
233 *((uint64_t*) lVirtAddr) = *(uint64_t*) lSrcPtr;
234 lNrBytesCopied += 8;
235 }
236 else if ((lNrBytes - lNrBytesCopied) >= 4) {
237 *((uint64_t*) lVirtAddr) = uint64_t(*(uint32_t*) lSrcPtr);
238 lNrBytesCopied += 4;
239 }
240 }
241
242 free(allocated);
243 }, lMessage.str());
244}
245
246
248{
249 return mLocked;
250}
251
252
254{
255 if ( flock(mFd, LOCK_EX) == -1 ) {
256 detail::MutexError lExc;
257 log(lExc, "Failed to lock device file ", Quote(mPath), "; errno=", Integer(errno), ", meaning ", Quote (strerror(errno)));
258 throw lExc;
259 }
260 mLocked = true;
261}
262
263
265{
266 if ( flock(mFd, LOCK_UN) == -1 ) {
267 log(Warning(), "Failed to unlock device file ", Quote(mPath), "; errno=", Integer(errno), ", meaning ", Quote (strerror(errno)));
268 }
269 else
270 mLocked = false;
271}
272
273
274std::string Mmap::getSharedMemName(const std::string& aPath)
275{
276 std::string lSanitizedPath(aPath);
277 std::replace(lSanitizedPath.begin(), lSanitizedPath.end(), '/', ':');
278
279 return "/uhal::ipbusmmap-2.0::" + lSanitizedPath;
280}
281
282
283Mmap::Mmap ( const std::string& aId, const URI& aUri ) :
284 IPbus< 2 , 0 > ( aId , aUri ),
285 mConnected(false),
286 mDeviceFile(aUri.mHostname, O_RDWR | O_SYNC),
289 mMaxInFlight(0),
290 mPageSize(0),
295{
296 mSleepDuration = std::chrono::microseconds(50);
297
298 for (const auto& lArg: aUri.mArguments) {
299 if (lArg.first == "sleep") {
300 mSleepDuration = std::chrono::microseconds(boost::lexical_cast<size_t>(lArg.second));
301 log (Notice() , "mmap client with URI ", Quote (uri()), " : Inter-poll-/-interrupt sleep duration set to ", boost::lexical_cast<size_t>(lArg.second), " us by URI 'sleep' attribute");
302 }
303 else if (lArg.first == "offset") {
304 const bool lIsHex = (lArg.second.find("0x") == 0) or (lArg.second.find("0X") == 0);
305 const size_t lOffset = (lIsHex ? boost::lexical_cast<HexTo<size_t> >(lArg.second) : boost::lexical_cast<size_t>(lArg.second));
306 mDeviceFile.setOffset(lOffset);
307 log (Notice(), "mmap client with URI ", Quote (uri()), " : Address offset set to ", Integer(lOffset, IntFmt<hex>()));
308 }
309 else if (lArg.first == "max_in_flight") {
310 mMaxInFlight = boost::lexical_cast<size_t>(lArg.second);
311 log (Notice() , "mmap client with URI ", Quote (uri()), " : 'Maximum number of packets in flight' set to ", boost::lexical_cast<size_t>(lArg.second), " by URI 'max_in_flight' attribute");
312 }
313 else if (lArg.first == "max_packet_size") {
314 mMaxPacketSize = boost::lexical_cast<size_t>(lArg.second);
315 log (Notice() , "mmap client with URI ", Quote (uri()), " : 'Maximum packet size (in 32-bit words) set to ", boost::lexical_cast<size_t>(lArg.second), " by URI 'max_packet_size' attribute");
316 }
317 else {
318 log (Warning() , "Unknown attribute ", Quote (lArg.first), " used in URI ", Quote(uri()));
319 }
320 }
321}
322
323
325{
326 disconnect();
327}
328
329
330void Mmap::implementDispatch ( std::shared_ptr< Buffers > aBuffers )
331{
332 log(Debug(), "mmap client ", Quote(id()), ": implementDispatch method called");
333
334 if ( ! mConnected )
335 connect();
336
337 if ( mReplyQueue.size() == mNumberOfPages )
338 read();
339 write(aBuffers);
340}
341
342
344{
345 log(Debug(), "mmap client ", Quote(id()), ": Flush method called");
346 while ( !mReplyQueue.empty() )
347 read();
348
350
352 mIPCMutex->endSession();
353}
354
355
357{
358 log(Info(), "mmap client ", Quote(id()), " : Closing device files since exception detected");
359
361
363
364 disconnect();
365
366 InnerProtocol::dispatchExceptionHandler();
367}
368
369
371{
372 if ( ! mConnected )
373 connect();
374
375 return mMaxPacketSize * 4;
376}
377
378
380{
381 if ( ! mConnected )
382 connect();
383
384 return mMaxPacketSize * 4;
385}
386
387
389{
391 connect(lLockGuard);
392}
393
394
396{
397 // Read current value of session counter when reading status info from FPGA
398 // (So that can check whether this info is up-to-date later on, when sending next request packet)
400 mIPCSessionCount = mIPCMutex->getCounter();
401
402 log ( Debug() , "mmap client is opening device file " , Quote ( mDeviceFile.getPath() ) );
403 std::vector<uint32_t> lValues;
404 mDeviceFile.read(0x0, 4, lValues);
405 log ( Debug(), "mmap client ", Quote(id()), ": Read status info from addr 0 (", Integer(lValues.at(0)), ", ", Integer(lValues.at(1)), ", ", Integer(lValues.at(2)), ", ", Integer(lValues.at(3)), "): ", detail::PacketFmt((const uint8_t*)lValues.data(), 4 * lValues.size()));
406
407 mNumberOfPages = lValues.at(0);
408 if ( (mMaxInFlight == 0) or (mMaxInFlight > mNumberOfPages) )
410 mPageSize = std::min(uint32_t(4096), lValues.at(1));
411 if ( (mMaxPacketSize == 0) or (mMaxPacketSize >= mPageSize) )
413 mIndexNextPage = lValues.at(2);
414 mPublishedReplyPageCount = lValues.at(3);
416
417 if (lValues.at(1) > 0xFFFF) {
418 exception::MmapInitialisationError lExc;
419 log (lExc, "Invalid page size, ", Integer(lValues.at(1)), ", reported in device file ", Quote(mDeviceFile.getPath()));
420 throw lExc;
421 }
422
424 exception::MmapInitialisationError lExc;
425 log (lExc, "Next page index, ", Integer(mIndexNextPage), ", reported in device file ", Quote(mDeviceFile.getPath()), " is inconsistent with number of pages, ", Integer(mNumberOfPages));
426 throw lExc;
427 }
428
429 mConnected = true;
430 log ( Info() , "mmap client ", Quote(id()), ": Connected to device at ", Quote(mDeviceFile.getPath()), "; FPGA has ", Integer(mNumberOfPages), " pages, each of size ", Integer(mPageSize), " words, index ", Integer(mIndexNextPage), " should be filled next (URI: ", Quote(uri()), ")" );
431}
432
433
435{
437 mConnected = false;
438}
439
440
441void Mmap::write(const std::shared_ptr<Buffers>& aBuffers)
442{
443 if (not mDeviceFile.haveLock()) {
445
447 mIPCMutex->startSession();
449
450 // If these two numbers don't match, another client/process has sent packets
451 // more recently than this client has, so must re-read status info
452 if (mIPCExternalSessionActive or (mIPCMutex->getCounter() != mIPCSessionCount)) {
453 connect(lGuard);
454 }
455 }
456
457 log (Info(), "mmap client ", Quote(id()), ": Writing ", Integer(aBuffers->sendCounter() / 4), "-word packet to page ", Integer(mIndexNextPage), " in ", mDeviceFile.getPath());
458
459 const uint32_t lHeaderWord = (0x10000 | (((aBuffers->sendCounter() / 4) - 1) & 0xFFFF));
460 std::vector<std::pair<const uint8_t*, size_t> > lDataToWrite;
461 lDataToWrite.push_back( std::make_pair(reinterpret_cast<const uint8_t*>(&lHeaderWord), sizeof lHeaderWord) );
462 lDataToWrite.push_back( std::make_pair(aBuffers->getSendBuffer(), aBuffers->sendCounter()) );
463
465 mDeviceFile.write(mIndexNextPage * 4 * mPageSize, lDataToWrite);
466 log (Debug(), "mmap client ", Quote(id()), ": Wrote " , Integer((aBuffers->sendCounter() / 4) + 1), " 32-bit words at address " , Integer(mIndexNextPage * 4 * mPageSize), " ... ", detail::PacketFmt(lDataToWrite));
467
469 mReplyQueue.push_back(aBuffers);
470}
471
472
474{
475 const size_t lPageIndexToRead = (mIndexNextPage - mReplyQueue.size() + mNumberOfPages) % mNumberOfPages;
476 SteadyClock_t::time_point lStartTime = SteadyClock_t::now();
477
479 {
480 uint32_t lHwPublishedPageCount = 0x0;
481
482 std::vector<uint32_t> lValues;
483 while ( true ) {
484 // FIXME : Improve by simply adding dmaWrite method that takes uint32_t ref as argument (or returns uint32_t)
486 mDeviceFile.read(0, 4, lValues);
487 lHwPublishedPageCount = lValues.at(3);
488 log (Debug(), "mmap client ", Quote(id()), ": Read status info from addr 0 (", Integer(lValues.at(0)), ", ", Integer(lValues.at(1)), ", ", Integer(lValues.at(2)), ", ", Integer(lValues.at(3)), "): ", detail::PacketFmt((const uint8_t*)lValues.data(), 4 * lValues.size()));
489
490 if (lHwPublishedPageCount != mPublishedReplyPageCount) {
491 mPublishedReplyPageCount = lHwPublishedPageCount;
492 break;
493 }
494 // FIXME: Throw if published page count is invalid number
495
496 if (SteadyClock_t::now() - lStartTime > std::chrono::microseconds(getBoostTimeoutPeriod().total_microseconds())) {
497 exception::MmapTimeout lExc;
498 log(lExc, "Next page (index ", Integer(lPageIndexToRead), " count ", Integer(mPublishedReplyPageCount+1), ") of mmap device '" + mDeviceFile.getPath() + "' is not ready after timeout period");
499 throw lExc;
500 }
501
502 log(Debug(), "mmap client ", Quote(id()), ": Trying to read page index ", Integer(lPageIndexToRead), " = count ", Integer(mReadReplyPageCount+1), "; published page count is ", Integer(lHwPublishedPageCount), "; sleeping for ", mSleepDuration.count(), "us");
503 if (mSleepDuration > std::chrono::microseconds(0))
504 std::this_thread::sleep_for( mSleepDuration );
505 lValues.clear();
506 }
507
508 log(Info(), "mmap client ", Quote(id()), ": Reading page ", Integer(lPageIndexToRead), " (published count ", Integer(lHwPublishedPageCount), ", surpasses required, ", Integer(mReadReplyPageCount + 1), ")");
509 }
511
512 // PART 1 : Read the page
513 std::shared_ptr<Buffers> lBuffers = mReplyQueue.front();
514 mReplyQueue.pop_front();
515
516 uint32_t lNrWordsToRead(lBuffers->replyCounter() >> 2);
517 lNrWordsToRead += 1;
518
519 std::vector<uint32_t> lPageContents;
521 mDeviceFile.read(4 + lPageIndexToRead * mPageSize, lNrWordsToRead , lPageContents);
522 lGuard.unlock();
523 log (Debug(), "mmap client ", Quote(id()), ": Read " , Integer(lNrWordsToRead), " 32-bit words from address " , Integer(16 + lPageIndexToRead * 4 * mPageSize), " ... ", detail::PacketFmt((const uint8_t*)lPageContents.data(), 4 * lPageContents.size()));
524
525 // PART 2 : Transfer to reply buffer
526 const std::deque< std::pair< uint8_t* , uint32_t > >& lReplyBuffers ( lBuffers->getReplyBuffer() );
527 size_t lNrWordsInPacket = (lPageContents.at(0) >> 16) + (lPageContents.at(0) & 0xFFFF);
528 if (lNrWordsInPacket != (lBuffers->replyCounter() >> 2))
529 log (Warning(), "mmap client ", Quote(id()), ": Expected reply packet to contain ", Integer(lBuffers->replyCounter() >> 2), " words, but it actually contains ", Integer(lNrWordsInPacket), " words");
530
531 size_t lNrBytesCopied = 0;
532 for (const auto& lBuffers: lReplyBuffers)
533 {
534 // Don't copy more of page than was written to, for cases when less data received than expected
535 if ( lNrBytesCopied >= 4*lNrWordsInPacket)
536 break;
537
538 size_t lNrBytesToCopy = std::min( lBuffers.second , uint32_t(4*lNrWordsInPacket - lNrBytesCopied) );
539 memcpy ( lBuffers.first, &lPageContents.at(1 + (lNrBytesCopied / 4)), lNrBytesToCopy );
540 lNrBytesCopied += lNrBytesToCopy;
541 }
542
543
544 // PART 3 : Validate the packet contents
545 uhal::exception::exception* lExc = NULL;
546 try
547 {
548 lExc = ClientInterface::validate ( lBuffers );
549 }
550 catch ( exception::exception& aExc )
551 {
552 exception::ValidationError lExc2;
553 log ( lExc2 , "Exception caught during reply validation for mmap device with URI " , Quote ( this->uri() ) , "; what returned: " , Quote ( aExc.what() ) );
554 throw lExc2;
555 }
556
557 if (lExc != NULL)
558 lExc->throwAsDerivedType();
559}
560
561
562} // end ns uhal
#define MAP_SIZE
void returnBufferToPool(std::shared_ptr< Buffers > &aBuffers)
Function to return a buffer to the buffer pool.
virtual exception::exception * validate(std::shared_ptr< Buffers > aBuffers)
Function which dispatch calls when the reply is received to check that the headers are as expected.
A class which provides the version-specific functionality for IPbus.
void write(const uint32_t aAddr, const std::vector< std::pair< const uint8_t *, size_t > > &aData)
const std::string & getPath() const
void setOffset(size_t aOffset)
File(const std::string &aPath, int aFlags)
bool haveLock() const
void setPath(const std::string &aPath)
void read(const uint32_t aAddr, const uint32_t aNrWords, std::vector< uint32_t > &aValues)
uint32_t mPageSize
std::chrono::microseconds mSleepDuration
virtual void Flush()
Concrete implementation of the synchronization function to block until all buffers have been sent,...
uint32_t mIndexNextPage
void disconnect()
Close the connection to the device.
uint32_t mReadReplyPageCount
std::deque< std::shared_ptr< Buffers > > mReplyQueue
The list of buffers still awaiting a reply.
uint64_t mIPCSessionCount
static std::string getSharedMemName(const std::string &)
bool mIPCExternalSessionActive
void write(const std::shared_ptr< Buffers > &aBuffers)
Write request packet to next page in host-to-FPGA device file.
virtual ~Mmap()
Destructor.
void connect()
Set up the connection to the device.
void implementDispatch(std::shared_ptr< Buffers > aBuffers)
Send the IPbus buffer to the target, read back the response and call the packing-protocol's validate ...
void read()
Read next pending reply packet from appropriate page of FPGA-to-host device file, and validate conten...
uint32_t getMaxSendSize()
Return the maximum size to be sent based on the buffer size in the target.
virtual void dispatchExceptionHandler()
Function which tidies up this protocol layer in the event of an exception.
uint32_t getMaxReplySize()
Return the maximum size of reply packet based on the buffer size in the target.
uint32_t mNumberOfPages
uint32_t mMaxPacketSize
uint32_t mMaxInFlight
Mmap(const Mmap &aMmap)
uint32_t mPublishedReplyPageCount
detail::SharedObject< detail::RobustSessionMutex > mIPCMutex
void protect(const std::function< void()> &, const std::string &)
Definition: SigBusGuard.cpp:98
Class used to display IPbus packet contents in human-readable format (e.g. in log messages)
Definition: PacketFmt.hpp:16
An abstract base exception class, including an interface to throw as the derived type (for passing ex...
Definition: exception.hpp:71
virtual const char * what() const
Function which returns the error message associated with an exception If no error message has previou...
Definition: exception.cpp:87
virtual void throwAsDerivedType()=0
Function which casts a pointer from the base type of this object to a derived type of this object and...
std::unique_lock< RobustSessionMutex > ScopedSessionLock
DebugLevel Debug
Definition: LogLevels.cpp:133
_Quote< T > Quote(const T &aT)
_Integer< T, IntFmt<> > Integer(const T &aT)
Forward declare a function which creates an instance of the ultra-lightweight wrapper from an integer...
ErrorLevel Error
Definition: LogLevels.cpp:61
void log(FatalLevel &aFatal, const T0 &aArg0)
Function to add a log entry at Fatal level.
Definition: log.hxx:18
WarningLevel Warning
Definition: LogLevels.cpp:79
InfoLevel Info
Definition: LogLevels.cpp:115
NoticeLevel Notice
Definition: LogLevels.cpp:97
Empty struct which acts as a dummy variable for passing the formatting information around.
Struct to store a URI when parsed by boost spirit.
Definition: URI.hpp:50
NameValuePairVectorType mArguments
The "key1=val1&key2=val2&key3=val3" part of a URI of the form "protocol://host:port/patha/pathb/blah....
Definition: URI.hpp:62