From d922e559bf3c8431c2c1ad88dcc5882239ca30da Mon Sep 17 00:00:00 2001 From: "Charles E. Rolke" Date: Thu, 20 Dec 2012 15:33:18 +0000 Subject: QPID-1726 ASF licensed, Qpid hosted store module Project standard: rename files from .hpp to .h git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1424532 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/src/qpid/legacystore/jrnl/aio.h | 153 ++++++ cpp/src/qpid/legacystore/jrnl/aio.hpp | 153 ------ cpp/src/qpid/legacystore/jrnl/aio_callback.h | 57 ++ cpp/src/qpid/legacystore/jrnl/aio_callback.hpp | 57 -- cpp/src/qpid/legacystore/jrnl/cvar.h | 87 +++ cpp/src/qpid/legacystore/jrnl/cvar.hpp | 87 --- cpp/src/qpid/legacystore/jrnl/data_tok.h | 172 ++++++ cpp/src/qpid/legacystore/jrnl/data_tok.hpp | 172 ------ cpp/src/qpid/legacystore/jrnl/deq_hdr.h | 141 +++++ cpp/src/qpid/legacystore/jrnl/deq_hdr.hpp | 141 ----- cpp/src/qpid/legacystore/jrnl/deq_rec.h | 103 ++++ cpp/src/qpid/legacystore/jrnl/deq_rec.hpp | 103 ---- cpp/src/qpid/legacystore/jrnl/enq_hdr.h | 165 ++++++ cpp/src/qpid/legacystore/jrnl/enq_hdr.hpp | 165 ------ cpp/src/qpid/legacystore/jrnl/enq_map.h | 127 +++++ cpp/src/qpid/legacystore/jrnl/enq_map.hpp | 127 ----- cpp/src/qpid/legacystore/jrnl/enq_rec.h | 116 ++++ cpp/src/qpid/legacystore/jrnl/enq_rec.hpp | 116 ---- cpp/src/qpid/legacystore/jrnl/enums.h | 108 ++++ cpp/src/qpid/legacystore/jrnl/enums.hpp | 108 ---- cpp/src/qpid/legacystore/jrnl/fcntl.h | 156 ++++++ cpp/src/qpid/legacystore/jrnl/fcntl.hpp | 156 ------ cpp/src/qpid/legacystore/jrnl/file_hdr.h | 211 ++++++++ cpp/src/qpid/legacystore/jrnl/file_hdr.hpp | 211 -------- cpp/src/qpid/legacystore/jrnl/jcfg.h | 91 ++++ cpp/src/qpid/legacystore/jrnl/jcfg.hpp | 91 ---- cpp/src/qpid/legacystore/jrnl/jcntl.h | 722 +++++++++++++++++++++++++ cpp/src/qpid/legacystore/jrnl/jcntl.hpp | 722 ------------------------- cpp/src/qpid/legacystore/jrnl/jdir.h | 379 +++++++++++++ cpp/src/qpid/legacystore/jrnl/jdir.hpp | 379 ------------- cpp/src/qpid/legacystore/jrnl/jerrno.h | 173 ++++++ cpp/src/qpid/legacystore/jrnl/jerrno.hpp | 173 ------ cpp/src/qpid/legacystore/jrnl/jexception.h | 142 +++++ cpp/src/qpid/legacystore/jrnl/jexception.hpp | 142 ----- cpp/src/qpid/legacystore/jrnl/jinf.h | 133 +++++ cpp/src/qpid/legacystore/jrnl/jinf.hpp | 133 ----- cpp/src/qpid/legacystore/jrnl/jrec.h | 183 +++++++ cpp/src/qpid/legacystore/jrnl/jrec.hpp | 183 ------- cpp/src/qpid/legacystore/jrnl/lp_map.h | 83 +++ cpp/src/qpid/legacystore/jrnl/lp_map.hpp | 83 --- cpp/src/qpid/legacystore/jrnl/lpmgr.h | 303 +++++++++++ cpp/src/qpid/legacystore/jrnl/lpmgr.hpp | 303 ----------- cpp/src/qpid/legacystore/jrnl/pmgr.h | 142 +++++ cpp/src/qpid/legacystore/jrnl/pmgr.hpp | 142 ----- cpp/src/qpid/legacystore/jrnl/rcvdat.h | 181 +++++++ cpp/src/qpid/legacystore/jrnl/rcvdat.hpp | 181 ------- cpp/src/qpid/legacystore/jrnl/rec_hdr.h | 143 +++++ cpp/src/qpid/legacystore/jrnl/rec_hdr.hpp | 143 ----- cpp/src/qpid/legacystore/jrnl/rec_tail.h | 98 ++++ cpp/src/qpid/legacystore/jrnl/rec_tail.hpp | 98 ---- cpp/src/qpid/legacystore/jrnl/rfc.h | 193 +++++++ cpp/src/qpid/legacystore/jrnl/rfc.hpp | 193 ------- cpp/src/qpid/legacystore/jrnl/rmgr.h | 114 ++++ cpp/src/qpid/legacystore/jrnl/rmgr.hpp | 114 ---- cpp/src/qpid/legacystore/jrnl/rrfc.h | 179 ++++++ cpp/src/qpid/legacystore/jrnl/rrfc.hpp | 179 ------ cpp/src/qpid/legacystore/jrnl/slock.h | 85 +++ cpp/src/qpid/legacystore/jrnl/slock.hpp | 85 --- cpp/src/qpid/legacystore/jrnl/smutex.h | 64 +++ cpp/src/qpid/legacystore/jrnl/smutex.hpp | 64 --- cpp/src/qpid/legacystore/jrnl/time_ns.h | 105 ++++ cpp/src/qpid/legacystore/jrnl/time_ns.hpp | 105 ---- cpp/src/qpid/legacystore/jrnl/txn_hdr.h | 125 +++++ cpp/src/qpid/legacystore/jrnl/txn_hdr.hpp | 125 ----- cpp/src/qpid/legacystore/jrnl/txn_map.h | 159 ++++++ cpp/src/qpid/legacystore/jrnl/txn_map.hpp | 159 ------ cpp/src/qpid/legacystore/jrnl/txn_rec.h | 101 ++++ cpp/src/qpid/legacystore/jrnl/txn_rec.hpp | 101 ---- cpp/src/qpid/legacystore/jrnl/wmgr.h | 147 +++++ cpp/src/qpid/legacystore/jrnl/wmgr.hpp | 147 ----- cpp/src/qpid/legacystore/jrnl/wrfc.h | 154 ++++++ cpp/src/qpid/legacystore/jrnl/wrfc.hpp | 154 ------ 72 files changed, 5795 insertions(+), 5795 deletions(-) create mode 100644 cpp/src/qpid/legacystore/jrnl/aio.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/aio.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/aio_callback.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/aio_callback.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/cvar.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/cvar.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/data_tok.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/data_tok.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/deq_hdr.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/deq_hdr.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/deq_rec.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/deq_rec.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/enq_hdr.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/enq_hdr.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/enq_map.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/enq_map.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/enq_rec.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/enq_rec.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/enums.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/enums.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/fcntl.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/fcntl.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/file_hdr.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/file_hdr.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/jcfg.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/jcfg.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/jcntl.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/jcntl.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/jdir.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/jdir.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/jerrno.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/jerrno.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/jexception.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/jexception.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/jinf.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/jinf.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/jrec.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/jrec.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/lp_map.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/lp_map.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/lpmgr.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/lpmgr.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/pmgr.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/pmgr.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/rcvdat.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/rcvdat.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/rec_hdr.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/rec_hdr.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/rec_tail.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/rec_tail.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/rfc.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/rfc.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/rmgr.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/rmgr.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/rrfc.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/rrfc.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/slock.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/slock.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/smutex.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/smutex.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/time_ns.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/time_ns.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/txn_hdr.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/txn_hdr.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/txn_map.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/txn_map.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/txn_rec.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/txn_rec.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/wmgr.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/wmgr.hpp create mode 100644 cpp/src/qpid/legacystore/jrnl/wrfc.h delete mode 100644 cpp/src/qpid/legacystore/jrnl/wrfc.hpp (limited to 'cpp') diff --git a/cpp/src/qpid/legacystore/jrnl/aio.h b/cpp/src/qpid/legacystore/jrnl/aio.h new file mode 100644 index 0000000000..082535c8c1 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/aio.h @@ -0,0 +1,153 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file aio.hpp + * + * Qpid asynchronous store plugin library + * + * This file contains an encapsulation of the libaio interface used + * by the journal. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_aio_hpp +#define mrg_journal_aio_hpp + +#include +#include +#include +#include + +namespace mrg +{ +namespace journal +{ + +typedef iocb aio_cb; +typedef io_event aio_event; + +/** + * \brief This class is a C++ wrapper class for the libaio functions used by the journal. Note that only those + * functions used by the journal are included here. This is not a complete implementation of all libaio functions. + */ +class aio +{ +public: + static inline int queue_init(int maxevents, io_context_t* ctxp) + { + return ::io_queue_init(maxevents, ctxp); + } + + static inline int queue_release(io_context_t ctx) + { + return ::io_queue_release(ctx); + } + + static inline int submit(io_context_t ctx, long nr, aio_cb* aios[]) + { + return ::io_submit(ctx, nr, aios); + } + + static inline int getevents(io_context_t ctx, long min_nr, long nr, aio_event* events, timespec* const timeout) + { + return ::io_getevents(ctx, min_nr, nr, events, timeout); + } + + /** + * \brief This function allows iocbs to be initialized with a pointer that can be re-used. This prepares an + * aio_cb struct for read use. (This is a wrapper for libaio's ::io_prep_pread() function.) + * + * \param aiocbp Pointer to the aio_cb struct to be prepared. + * \param fd File descriptor to be used for read. + * \param buf Pointer to buffer in which read data is to be placed. + * \param count Number of bytes to read - buffer must be large enough. + * \param offset Offset within file from which data will be read. + */ + static inline void prep_pread(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) + { + ::io_prep_pread(aiocbp, fd, buf, count, offset); + } + + /** + * \brief Special version of libaio's io_prep_pread() which preserves the value of the data pointer. This allows + * iocbs to be initialized with a pointer that can be re-used. This prepares a aio_cb struct for read use. + * + * \param aiocbp Pointer to the aio_cb struct to be prepared. + * \param fd File descriptor to be used for read. + * \param buf Pointer to buffer in which read data is to be placed. + * \param count Number of bytes to read - buffer must be large enough. + * \param offset Offset within file from which data will be read. + */ + static inline void prep_pread_2(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) + { + std::memset((void*) ((char*) aiocbp + sizeof(void*)), 0, sizeof(aio_cb) - sizeof(void*)); + aiocbp->aio_fildes = fd; + aiocbp->aio_lio_opcode = IO_CMD_PREAD; + aiocbp->aio_reqprio = 0; + aiocbp->u.c.buf = buf; + aiocbp->u.c.nbytes = count; + aiocbp->u.c.offset = offset; + } + + /** + * \brief This function allows iocbs to be initialized with a pointer that can be re-used. This function prepares + * an aio_cb struct for write use. (This is a wrapper for libaio's ::io_prep_pwrite() function.) + * + * \param aiocbp Pointer to the aio_cb struct to be prepared. + * \param fd File descriptor to be used for write. + * \param buf Pointer to buffer in which data to be written is located. + * \param count Number of bytes to write. + * \param offset Offset within file to which data will be written. + */ + static inline void prep_pwrite(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) + { + ::io_prep_pwrite(aiocbp, fd, buf, count, offset); + } + + /** + * \brief Special version of libaio's io_prep_pwrite() which preserves the value of the data pointer. This allows + * iocbs to be initialized with a pointer that can be re-used. This function prepares an aio_cb struct for write + * use. + * + * \param aiocbp Pointer to the aio_cb struct to be prepared. + * \param fd File descriptor to be used for write. + * \param buf Pointer to buffer in which data to be written is located. + * \param count Number of bytes to write. + * \param offset Offset within file to which data will be written. + */ + static inline void prep_pwrite_2(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) + { + std::memset((void*) ((char*) aiocbp + sizeof(void*)), 0, sizeof(aio_cb) - sizeof(void*)); + aiocbp->aio_fildes = fd; + aiocbp->aio_lio_opcode = IO_CMD_PWRITE; + aiocbp->aio_reqprio = 0; + aiocbp->u.c.buf = buf; + aiocbp->u.c.nbytes = count; + aiocbp->u.c.offset = offset; + } +}; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_aio_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/aio.hpp b/cpp/src/qpid/legacystore/jrnl/aio.hpp deleted file mode 100644 index 082535c8c1..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/aio.hpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file aio.hpp - * - * Qpid asynchronous store plugin library - * - * This file contains an encapsulation of the libaio interface used - * by the journal. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_aio_hpp -#define mrg_journal_aio_hpp - -#include -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - -typedef iocb aio_cb; -typedef io_event aio_event; - -/** - * \brief This class is a C++ wrapper class for the libaio functions used by the journal. Note that only those - * functions used by the journal are included here. This is not a complete implementation of all libaio functions. - */ -class aio -{ -public: - static inline int queue_init(int maxevents, io_context_t* ctxp) - { - return ::io_queue_init(maxevents, ctxp); - } - - static inline int queue_release(io_context_t ctx) - { - return ::io_queue_release(ctx); - } - - static inline int submit(io_context_t ctx, long nr, aio_cb* aios[]) - { - return ::io_submit(ctx, nr, aios); - } - - static inline int getevents(io_context_t ctx, long min_nr, long nr, aio_event* events, timespec* const timeout) - { - return ::io_getevents(ctx, min_nr, nr, events, timeout); - } - - /** - * \brief This function allows iocbs to be initialized with a pointer that can be re-used. This prepares an - * aio_cb struct for read use. (This is a wrapper for libaio's ::io_prep_pread() function.) - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for read. - * \param buf Pointer to buffer in which read data is to be placed. - * \param count Number of bytes to read - buffer must be large enough. - * \param offset Offset within file from which data will be read. - */ - static inline void prep_pread(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - ::io_prep_pread(aiocbp, fd, buf, count, offset); - } - - /** - * \brief Special version of libaio's io_prep_pread() which preserves the value of the data pointer. This allows - * iocbs to be initialized with a pointer that can be re-used. This prepares a aio_cb struct for read use. - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for read. - * \param buf Pointer to buffer in which read data is to be placed. - * \param count Number of bytes to read - buffer must be large enough. - * \param offset Offset within file from which data will be read. - */ - static inline void prep_pread_2(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - std::memset((void*) ((char*) aiocbp + sizeof(void*)), 0, sizeof(aio_cb) - sizeof(void*)); - aiocbp->aio_fildes = fd; - aiocbp->aio_lio_opcode = IO_CMD_PREAD; - aiocbp->aio_reqprio = 0; - aiocbp->u.c.buf = buf; - aiocbp->u.c.nbytes = count; - aiocbp->u.c.offset = offset; - } - - /** - * \brief This function allows iocbs to be initialized with a pointer that can be re-used. This function prepares - * an aio_cb struct for write use. (This is a wrapper for libaio's ::io_prep_pwrite() function.) - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for write. - * \param buf Pointer to buffer in which data to be written is located. - * \param count Number of bytes to write. - * \param offset Offset within file to which data will be written. - */ - static inline void prep_pwrite(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - ::io_prep_pwrite(aiocbp, fd, buf, count, offset); - } - - /** - * \brief Special version of libaio's io_prep_pwrite() which preserves the value of the data pointer. This allows - * iocbs to be initialized with a pointer that can be re-used. This function prepares an aio_cb struct for write - * use. - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for write. - * \param buf Pointer to buffer in which data to be written is located. - * \param count Number of bytes to write. - * \param offset Offset within file to which data will be written. - */ - static inline void prep_pwrite_2(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - std::memset((void*) ((char*) aiocbp + sizeof(void*)), 0, sizeof(aio_cb) - sizeof(void*)); - aiocbp->aio_fildes = fd; - aiocbp->aio_lio_opcode = IO_CMD_PWRITE; - aiocbp->aio_reqprio = 0; - aiocbp->u.c.buf = buf; - aiocbp->u.c.nbytes = count; - aiocbp->u.c.offset = offset; - } -}; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_aio_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/aio_callback.h b/cpp/src/qpid/legacystore/jrnl/aio_callback.h new file mode 100644 index 0000000000..a65e9a784b --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/aio_callback.h @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file aio_callback.hpp + * + * Qpid asynchronous store plugin library + * + * This file contains the definition for the AIO callback function + * pointer. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_aio_callback_hpp +#define mrg_journal_aio_callback_hpp + +#include +#include + +namespace mrg +{ +namespace journal +{ + + class data_tok; + + class aio_callback + { + public: + virtual ~aio_callback() {} + virtual void wr_aio_cb(std::vector& dtokl) = 0; + virtual void rd_aio_cb(std::vector& pil) = 0; + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_aio_callback_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/aio_callback.hpp b/cpp/src/qpid/legacystore/jrnl/aio_callback.hpp deleted file mode 100644 index a65e9a784b..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/aio_callback.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file aio_callback.hpp - * - * Qpid asynchronous store plugin library - * - * This file contains the definition for the AIO callback function - * pointer. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_aio_callback_hpp -#define mrg_journal_aio_callback_hpp - -#include -#include - -namespace mrg -{ -namespace journal -{ - - class data_tok; - - class aio_callback - { - public: - virtual ~aio_callback() {} - virtual void wr_aio_cb(std::vector& dtokl) = 0; - virtual void rd_aio_cb(std::vector& pil) = 0; - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_aio_callback_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/cvar.h b/cpp/src/qpid/legacystore/jrnl/cvar.h new file mode 100644 index 0000000000..bbc2e8e9fc --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/cvar.h @@ -0,0 +1,87 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file cvar.hpp + * + * Qpid asynchronous store plugin library + * + * This file contains a posix condition variable class. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_cvar_hpp +#define mrg_journal_cvar_hpp + +#include +#include "jrnl/jerrno.hpp" +#include "jrnl/jexception.hpp" +#include "jrnl/smutex.hpp" +#include "jrnl/time_ns.hpp" +#include +#include + +namespace mrg +{ +namespace journal +{ + + // Ultra-simple thread condition variable class + class cvar + { + private: + const smutex& _sm; + pthread_cond_t _c; + public: + inline cvar(const smutex& sm) : _sm(sm) { ::pthread_cond_init(&_c, 0); } + inline ~cvar() { ::pthread_cond_destroy(&_c); } + inline void wait() + { + PTHREAD_CHK(::pthread_cond_wait(&_c, _sm.get()), "::pthread_cond_wait", "cvar", "wait"); + } + inline void timedwait(timespec& ts) + { + PTHREAD_CHK(::pthread_cond_timedwait(&_c, _sm.get(), &ts), "::pthread_cond_timedwait", "cvar", "timedwait"); + } + inline bool waitintvl(const long intvl_ns) + { + time_ns t; t.now(); t+=intvl_ns; + int ret = ::pthread_cond_timedwait(&_c, _sm.get(), &t); + if (ret == ETIMEDOUT) + return true; + PTHREAD_CHK(ret, "::pthread_cond_timedwait", "cvar", "waitintvl"); + return false; + } + inline void signal() + { + PTHREAD_CHK(::pthread_cond_signal(&_c), "::pthread_cond_signal", "cvar", "notify"); + } + inline void broadcast() + { + PTHREAD_CHK(::pthread_cond_broadcast(&_c), "::pthread_cond_broadcast", "cvar", "broadcast"); + } + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_cvar_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/cvar.hpp b/cpp/src/qpid/legacystore/jrnl/cvar.hpp deleted file mode 100644 index bbc2e8e9fc..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/cvar.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file cvar.hpp - * - * Qpid asynchronous store plugin library - * - * This file contains a posix condition variable class. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_cvar_hpp -#define mrg_journal_cvar_hpp - -#include -#include "jrnl/jerrno.hpp" -#include "jrnl/jexception.hpp" -#include "jrnl/smutex.hpp" -#include "jrnl/time_ns.hpp" -#include -#include - -namespace mrg -{ -namespace journal -{ - - // Ultra-simple thread condition variable class - class cvar - { - private: - const smutex& _sm; - pthread_cond_t _c; - public: - inline cvar(const smutex& sm) : _sm(sm) { ::pthread_cond_init(&_c, 0); } - inline ~cvar() { ::pthread_cond_destroy(&_c); } - inline void wait() - { - PTHREAD_CHK(::pthread_cond_wait(&_c, _sm.get()), "::pthread_cond_wait", "cvar", "wait"); - } - inline void timedwait(timespec& ts) - { - PTHREAD_CHK(::pthread_cond_timedwait(&_c, _sm.get(), &ts), "::pthread_cond_timedwait", "cvar", "timedwait"); - } - inline bool waitintvl(const long intvl_ns) - { - time_ns t; t.now(); t+=intvl_ns; - int ret = ::pthread_cond_timedwait(&_c, _sm.get(), &t); - if (ret == ETIMEDOUT) - return true; - PTHREAD_CHK(ret, "::pthread_cond_timedwait", "cvar", "waitintvl"); - return false; - } - inline void signal() - { - PTHREAD_CHK(::pthread_cond_signal(&_c), "::pthread_cond_signal", "cvar", "notify"); - } - inline void broadcast() - { - PTHREAD_CHK(::pthread_cond_broadcast(&_c), "::pthread_cond_broadcast", "cvar", "broadcast"); - } - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_cvar_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/data_tok.h b/cpp/src/qpid/legacystore/jrnl/data_tok.h new file mode 100644 index 0000000000..16537f59cc --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/data_tok.h @@ -0,0 +1,172 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file data_tok.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::data_tok (data block token). + * See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_data_tok_hpp +#define mrg_journal_data_tok_hpp + +namespace mrg +{ +namespace journal +{ +class data_tok; +} +} + +#include +#include +#include "jrnl/smutex.hpp" +#include +#include +#include + +namespace mrg +{ + +namespace journal +{ + + /** + * \class data_tok + * \brief Data block token (data_tok) used to track wstate of a data block through asynchronous + * I/O process + */ + class data_tok + { + public: + // TODO: Fix this, separate write state from operation + // ie: wstate = NONE, CACHED, PART, SUBM, COMPL + // op = ENQUEUE, DEQUEUE, ABORT, COMMIT + enum write_state + { + NONE, ///< Data block not sent to journal + ENQ_CACHED, ///< Data block enqueue written to page cache + ENQ_PART, ///< Data block part-submitted to AIO, waiting for page buffer to free up + ENQ_SUBM, ///< Data block enqueue submitted to AIO + ENQ, ///< Data block enqueue AIO write complete (enqueue complete) + DEQ_CACHED, ///< Data block dequeue written to page cache + DEQ_PART, ///< Data block part-submitted to AIO, waiting for page buffer to free up + DEQ_SUBM, ///< Data block dequeue submitted to AIO + DEQ, ///< Data block dequeue AIO write complete (dequeue complete) + ABORT_CACHED, + ABORT_PART, + ABORT_SUBM, + ABORTED, + COMMIT_CACHED, + COMMIT_PART, + COMMIT_SUBM, + COMMITTED + }; + + enum read_state + { + UNREAD, ///< Data block not read + READ_PART, ///< Data block is part-read; waiting for page buffer to fill + SKIP_PART, ///< Prev. dequeued dblock is part-skipped; waiting for page buffer to fill + READ ///< Data block is fully read + }; + + protected: + static smutex _mutex; + static u_int64_t _cnt; + u_int64_t _icnt; + write_state _wstate; ///< Enqueued / dequeued state of data + read_state _rstate; ///< Read state of data + std::size_t _dsize; ///< Data size in bytes + u_int32_t _dblks_written; ///< Data blocks read/written + u_int32_t _dblks_read; ///< Data blocks read/written + u_int32_t _pg_cnt; ///< Page counter - incr for each page containing part of data + u_int16_t _fid; ///< FID containing header of enqueue record + u_int64_t _rid; ///< RID of data set by enqueue operation + std::string _xid; ///< XID set by enqueue operation + u_int64_t _dequeue_rid; ///< RID of data set by dequeue operation + bool _external_rid; ///< Flag to indicate external setting of rid + + public: + data_tok(); + virtual ~data_tok(); + + inline u_int64_t id() const { return _icnt; } + inline write_state wstate() const { return _wstate; } + const char* wstate_str() const; + static const char* wstate_str(write_state wstate); + inline read_state rstate() const { return _rstate; } + const char* rstate_str() const; + static const char* rstate_str(read_state rstate); + inline bool is_writable() const { return _wstate == NONE || _wstate == ENQ_PART; } + inline bool is_enqueued() const { return _wstate == ENQ; } + inline bool is_readable() const { return _wstate == ENQ; } + inline bool is_read() const { return _rstate == READ; } + inline bool is_dequeueable() const { return _wstate == ENQ || _wstate == DEQ_PART; } + inline void set_wstate(const write_state wstate) { _wstate = wstate; } + void set_rstate(const read_state rstate); + inline std::size_t dsize() const { return _dsize; } + inline void set_dsize(std::size_t dsize) { _dsize = dsize; } + + inline u_int32_t dblocks_written() const { return _dblks_written; } + inline void incr_dblocks_written(u_int32_t dblks_written) + { _dblks_written += dblks_written; } + inline void set_dblocks_written(u_int32_t dblks_written) { _dblks_written = dblks_written; } + + inline u_int32_t dblocks_read() const { return _dblks_read; } + inline void incr_dblocks_read(u_int32_t dblks_read) { _dblks_read += dblks_read; } + inline void set_dblocks_read(u_int32_t dblks_read) { _dblks_read = dblks_read; } + + inline u_int32_t pg_cnt() const { return _pg_cnt; } + inline u_int32_t incr_pg_cnt() { return ++_pg_cnt; } + inline u_int32_t decr_pg_cnt() { assert(_pg_cnt != 0); return --_pg_cnt; } + + inline u_int16_t fid() const { return _fid; } + inline void set_fid(const u_int16_t fid) { _fid = fid; } + inline u_int64_t rid() const { return _rid; } + inline void set_rid(const u_int64_t rid) { _rid = rid; } + inline u_int64_t dequeue_rid() const {return _dequeue_rid; } + inline void set_dequeue_rid(const u_int64_t rid) { _dequeue_rid = rid; } + inline bool external_rid() const { return _external_rid; } + inline void set_external_rid(const bool external_rid) { _external_rid = external_rid; } + + inline bool has_xid() const { return !_xid.empty(); } + inline const std::string& xid() const { return _xid; } + inline void clear_xid() { _xid.clear(); } + inline void set_xid(const std::string& xid) { _xid.assign(xid); } + inline void set_xid(const void* xidp, const std::size_t xid_len) + { _xid.assign((const char*)xidp, xid_len); } + + void reset(); + + // debug aid + std::string status_str() const; + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_data_tok_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/data_tok.hpp b/cpp/src/qpid/legacystore/jrnl/data_tok.hpp deleted file mode 100644 index 16537f59cc..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/data_tok.hpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file data_tok.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::data_tok (data block token). - * See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_data_tok_hpp -#define mrg_journal_data_tok_hpp - -namespace mrg -{ -namespace journal -{ -class data_tok; -} -} - -#include -#include -#include "jrnl/smutex.hpp" -#include -#include -#include - -namespace mrg -{ - -namespace journal -{ - - /** - * \class data_tok - * \brief Data block token (data_tok) used to track wstate of a data block through asynchronous - * I/O process - */ - class data_tok - { - public: - // TODO: Fix this, separate write state from operation - // ie: wstate = NONE, CACHED, PART, SUBM, COMPL - // op = ENQUEUE, DEQUEUE, ABORT, COMMIT - enum write_state - { - NONE, ///< Data block not sent to journal - ENQ_CACHED, ///< Data block enqueue written to page cache - ENQ_PART, ///< Data block part-submitted to AIO, waiting for page buffer to free up - ENQ_SUBM, ///< Data block enqueue submitted to AIO - ENQ, ///< Data block enqueue AIO write complete (enqueue complete) - DEQ_CACHED, ///< Data block dequeue written to page cache - DEQ_PART, ///< Data block part-submitted to AIO, waiting for page buffer to free up - DEQ_SUBM, ///< Data block dequeue submitted to AIO - DEQ, ///< Data block dequeue AIO write complete (dequeue complete) - ABORT_CACHED, - ABORT_PART, - ABORT_SUBM, - ABORTED, - COMMIT_CACHED, - COMMIT_PART, - COMMIT_SUBM, - COMMITTED - }; - - enum read_state - { - UNREAD, ///< Data block not read - READ_PART, ///< Data block is part-read; waiting for page buffer to fill - SKIP_PART, ///< Prev. dequeued dblock is part-skipped; waiting for page buffer to fill - READ ///< Data block is fully read - }; - - protected: - static smutex _mutex; - static u_int64_t _cnt; - u_int64_t _icnt; - write_state _wstate; ///< Enqueued / dequeued state of data - read_state _rstate; ///< Read state of data - std::size_t _dsize; ///< Data size in bytes - u_int32_t _dblks_written; ///< Data blocks read/written - u_int32_t _dblks_read; ///< Data blocks read/written - u_int32_t _pg_cnt; ///< Page counter - incr for each page containing part of data - u_int16_t _fid; ///< FID containing header of enqueue record - u_int64_t _rid; ///< RID of data set by enqueue operation - std::string _xid; ///< XID set by enqueue operation - u_int64_t _dequeue_rid; ///< RID of data set by dequeue operation - bool _external_rid; ///< Flag to indicate external setting of rid - - public: - data_tok(); - virtual ~data_tok(); - - inline u_int64_t id() const { return _icnt; } - inline write_state wstate() const { return _wstate; } - const char* wstate_str() const; - static const char* wstate_str(write_state wstate); - inline read_state rstate() const { return _rstate; } - const char* rstate_str() const; - static const char* rstate_str(read_state rstate); - inline bool is_writable() const { return _wstate == NONE || _wstate == ENQ_PART; } - inline bool is_enqueued() const { return _wstate == ENQ; } - inline bool is_readable() const { return _wstate == ENQ; } - inline bool is_read() const { return _rstate == READ; } - inline bool is_dequeueable() const { return _wstate == ENQ || _wstate == DEQ_PART; } - inline void set_wstate(const write_state wstate) { _wstate = wstate; } - void set_rstate(const read_state rstate); - inline std::size_t dsize() const { return _dsize; } - inline void set_dsize(std::size_t dsize) { _dsize = dsize; } - - inline u_int32_t dblocks_written() const { return _dblks_written; } - inline void incr_dblocks_written(u_int32_t dblks_written) - { _dblks_written += dblks_written; } - inline void set_dblocks_written(u_int32_t dblks_written) { _dblks_written = dblks_written; } - - inline u_int32_t dblocks_read() const { return _dblks_read; } - inline void incr_dblocks_read(u_int32_t dblks_read) { _dblks_read += dblks_read; } - inline void set_dblocks_read(u_int32_t dblks_read) { _dblks_read = dblks_read; } - - inline u_int32_t pg_cnt() const { return _pg_cnt; } - inline u_int32_t incr_pg_cnt() { return ++_pg_cnt; } - inline u_int32_t decr_pg_cnt() { assert(_pg_cnt != 0); return --_pg_cnt; } - - inline u_int16_t fid() const { return _fid; } - inline void set_fid(const u_int16_t fid) { _fid = fid; } - inline u_int64_t rid() const { return _rid; } - inline void set_rid(const u_int64_t rid) { _rid = rid; } - inline u_int64_t dequeue_rid() const {return _dequeue_rid; } - inline void set_dequeue_rid(const u_int64_t rid) { _dequeue_rid = rid; } - inline bool external_rid() const { return _external_rid; } - inline void set_external_rid(const bool external_rid) { _external_rid = external_rid; } - - inline bool has_xid() const { return !_xid.empty(); } - inline const std::string& xid() const { return _xid; } - inline void clear_xid() { _xid.clear(); } - inline void set_xid(const std::string& xid) { _xid.assign(xid); } - inline void set_xid(const void* xidp, const std::size_t xid_len) - { _xid.assign((const char*)xidp, xid_len); } - - void reset(); - - // debug aid - std::string status_str() const; - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_data_tok_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/deq_hdr.h b/cpp/src/qpid/legacystore/jrnl/deq_hdr.h new file mode 100644 index 0000000000..48b8673dc3 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/deq_hdr.h @@ -0,0 +1,141 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file deq_hdr.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::deq_hdr (dequeue record), + * used to dequeue a previously enqueued record. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_deq_hdr_hpp +#define mrg_journal_deq_hdr_hpp + +#include +#include "jrnl/rec_hdr.hpp" + +namespace mrg +{ +namespace journal +{ + +#pragma pack(1) + + /** + * \brief Struct for dequeue record. + * + * Struct for dequeue record. If this record has a non-zero xidsize field (i.e., there is a + * valid XID), then this header is followed by the XID of xidsize bytes and a rec_tail. If, + * on the other hand, this record has a zero xidsize (i.e., there is no XID), then the rec_tail + * is absent. + * + * Note that this record had its own rid distinct from the rid of the record it is dequeueing. + * The rid field below is the rid of the dequeue record itself; the deq-rid field is the rid of a + * previous enqueue record being dequeued by this record. + * + * Record header info in binary format (32 bytes): + *
+    *   0                           7
+    * +---+---+---+---+---+---+---+---+  -+
+    * |     magic     | v | e | flags |   |
+    * +---+---+---+---+---+---+---+---+   | struct hdr
+    * |              rid              |   |
+    * +---+---+---+---+---+---+---+---+  -+
+    * |            deq-rid            |
+    * +---+---+---+---+---+---+---+---+
+    * |            xidsize            |
+    * +---+---+---+---+---+---+---+---+
+    * v = file version (If the format or encoding of this file changes, then this
+    *     number should be incremented)
+    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
+    * 
+ * + * Note that journal files should be transferable between 32- and 64-bit + * hardware of the same endianness, but not between hardware of opposite + * entianness without some sort of binary conversion utility. Thus buffering + * will be needed for types that change size between 32- and 64-bit compiles. + */ + struct deq_hdr : rec_hdr + { + u_int64_t _deq_rid; ///< Record ID of dequeued record +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t +#endif + std::size_t _xidsize; ///< XID size +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t +#endif + static const u_int16_t DEQ_HDR_TXNCMPLCOMMIT_MASK = 0x10; + + /** + * \brief Default constructor, which sets all values to 0. + */ + inline deq_hdr(): rec_hdr(), _deq_rid(0), +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif + _xidsize(0) +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + , _filler0(0) +#endif + {} + + /** + * \brief Convenience constructor which initializes values during construction. + */ + inline deq_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, + const u_int64_t deq_rid, const std::size_t xidsize, const bool owi, + const bool txn_coml_commit = false): + rec_hdr(magic, version, rid, owi), _deq_rid(deq_rid), +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif + _xidsize(xidsize) +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + , _filler0(0) +#endif + { set_txn_coml_commit(txn_coml_commit); } + + + inline bool is_txn_coml_commit() const { return _uflag & DEQ_HDR_TXNCMPLCOMMIT_MASK; } + + inline void set_txn_coml_commit(const bool commit) + { + _uflag = commit ? _uflag | DEQ_HDR_TXNCMPLCOMMIT_MASK : + _uflag & (~DEQ_HDR_TXNCMPLCOMMIT_MASK); + } + + /** + * \brief Returns the size of the header in bytes. + */ + inline static std::size_t size() { return sizeof(deq_hdr); } + }; + +#pragma pack() + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_deq_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/deq_hdr.hpp b/cpp/src/qpid/legacystore/jrnl/deq_hdr.hpp deleted file mode 100644 index 48b8673dc3..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/deq_hdr.hpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file deq_hdr.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::deq_hdr (dequeue record), - * used to dequeue a previously enqueued record. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_deq_hdr_hpp -#define mrg_journal_deq_hdr_hpp - -#include -#include "jrnl/rec_hdr.hpp" - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for dequeue record. - * - * Struct for dequeue record. If this record has a non-zero xidsize field (i.e., there is a - * valid XID), then this header is followed by the XID of xidsize bytes and a rec_tail. If, - * on the other hand, this record has a zero xidsize (i.e., there is no XID), then the rec_tail - * is absent. - * - * Note that this record had its own rid distinct from the rid of the record it is dequeueing. - * The rid field below is the rid of the dequeue record itself; the deq-rid field is the rid of a - * previous enqueue record being dequeued by this record. - * - * Record header info in binary format (32 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+  -+
-    * |     magic     | v | e | flags |   |
-    * +---+---+---+---+---+---+---+---+   | struct hdr
-    * |              rid              |   |
-    * +---+---+---+---+---+---+---+---+  -+
-    * |            deq-rid            |
-    * +---+---+---+---+---+---+---+---+
-    * |            xidsize            |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct deq_hdr : rec_hdr - { - u_int64_t _deq_rid; ///< Record ID of dequeued record -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _xidsize; ///< XID size -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t -#endif - static const u_int16_t DEQ_HDR_TXNCMPLCOMMIT_MASK = 0x10; - - /** - * \brief Default constructor, which sets all values to 0. - */ - inline deq_hdr(): rec_hdr(), _deq_rid(0), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(0) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler0(0) -#endif - {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline deq_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const u_int64_t deq_rid, const std::size_t xidsize, const bool owi, - const bool txn_coml_commit = false): - rec_hdr(magic, version, rid, owi), _deq_rid(deq_rid), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(xidsize) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler0(0) -#endif - { set_txn_coml_commit(txn_coml_commit); } - - - inline bool is_txn_coml_commit() const { return _uflag & DEQ_HDR_TXNCMPLCOMMIT_MASK; } - - inline void set_txn_coml_commit(const bool commit) - { - _uflag = commit ? _uflag | DEQ_HDR_TXNCMPLCOMMIT_MASK : - _uflag & (~DEQ_HDR_TXNCMPLCOMMIT_MASK); - } - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(deq_hdr); } - }; - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_deq_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/deq_rec.h b/cpp/src/qpid/legacystore/jrnl/deq_rec.h new file mode 100644 index 0000000000..a3059035e3 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/deq_rec.h @@ -0,0 +1,103 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file deq_rec.hpp + * + * Qpid asynchronous store plugin library + * + * This file contains the code for the mrg::journal::deq_rec (journal dequeue + * record) class. See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_deq_rec_hpp +#define mrg_journal_deq_rec_hpp + +namespace mrg +{ +namespace journal +{ +class deq_rec; +} +} + +#include +#include "jrnl/deq_hdr.hpp" +#include "jrnl/jrec.hpp" + +namespace mrg +{ +namespace journal +{ + + /** + * \class deq_rec + * \brief Class to handle a single journal dequeue record. + */ + class deq_rec : public jrec + { + private: + deq_hdr _deq_hdr; ///< Dequeue header + const void* _xidp; ///< xid pointer for encoding (writing to disk) + void* _buff; ///< Pointer to buffer to receive data read from disk + rec_tail _deq_tail; ///< Record tail, only encoded if XID is present + + public: + // constructor used for read operations and xid will have memory allocated + deq_rec(); + // constructor used for write operations, where xid already exists + deq_rec(const u_int64_t rid, const u_int64_t drid, const void* const xidp, + const std::size_t xidlen, const bool owi, const bool txn_coml_commit); + virtual ~deq_rec(); + + // Prepare instance for use in reading data from journal + void reset(); + // Prepare instance for use in writing data to journal + void reset(const u_int64_t rid, const u_int64_t drid, const void* const xidp, + const std::size_t xidlen, const bool owi, const bool txn_coml_commit); + u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks); + u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, + u_int32_t max_size_dblks); + // Decode used for recover + bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs); + + inline bool is_txn_coml_commit() const { return _deq_hdr.is_txn_coml_commit(); } + inline u_int64_t rid() const { return _deq_hdr._rid; } + inline u_int64_t deq_rid() const { return _deq_hdr._deq_rid; } + std::size_t get_xid(void** const xidpp); + std::string& str(std::string& str) const; + inline std::size_t data_size() const { return 0; } // This record never carries data + std::size_t xid_size() const; + std::size_t rec_size() const; + + private: + virtual void chk_hdr() const; + virtual void chk_hdr(u_int64_t rid) const; + virtual void chk_tail() const; + virtual void clean(); + }; // class deq_rec + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_deq_rec_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/deq_rec.hpp b/cpp/src/qpid/legacystore/jrnl/deq_rec.hpp deleted file mode 100644 index a3059035e3..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/deq_rec.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file deq_rec.hpp - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::deq_rec (journal dequeue - * record) class. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_deq_rec_hpp -#define mrg_journal_deq_rec_hpp - -namespace mrg -{ -namespace journal -{ -class deq_rec; -} -} - -#include -#include "jrnl/deq_hdr.hpp" -#include "jrnl/jrec.hpp" - -namespace mrg -{ -namespace journal -{ - - /** - * \class deq_rec - * \brief Class to handle a single journal dequeue record. - */ - class deq_rec : public jrec - { - private: - deq_hdr _deq_hdr; ///< Dequeue header - const void* _xidp; ///< xid pointer for encoding (writing to disk) - void* _buff; ///< Pointer to buffer to receive data read from disk - rec_tail _deq_tail; ///< Record tail, only encoded if XID is present - - public: - // constructor used for read operations and xid will have memory allocated - deq_rec(); - // constructor used for write operations, where xid already exists - deq_rec(const u_int64_t rid, const u_int64_t drid, const void* const xidp, - const std::size_t xidlen, const bool owi, const bool txn_coml_commit); - virtual ~deq_rec(); - - // Prepare instance for use in reading data from journal - void reset(); - // Prepare instance for use in writing data to journal - void reset(const u_int64_t rid, const u_int64_t drid, const void* const xidp, - const std::size_t xidlen, const bool owi, const bool txn_coml_commit); - u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks); - u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks); - // Decode used for recover - bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs); - - inline bool is_txn_coml_commit() const { return _deq_hdr.is_txn_coml_commit(); } - inline u_int64_t rid() const { return _deq_hdr._rid; } - inline u_int64_t deq_rid() const { return _deq_hdr._deq_rid; } - std::size_t get_xid(void** const xidpp); - std::string& str(std::string& str) const; - inline std::size_t data_size() const { return 0; } // This record never carries data - std::size_t xid_size() const; - std::size_t rec_size() const; - - private: - virtual void chk_hdr() const; - virtual void chk_hdr(u_int64_t rid) const; - virtual void chk_tail() const; - virtual void clean(); - }; // class deq_rec - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_deq_rec_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/enq_hdr.h b/cpp/src/qpid/legacystore/jrnl/enq_hdr.h new file mode 100644 index 0000000000..a593db59c0 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/enq_hdr.h @@ -0,0 +1,165 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file enq_hdr.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::enq_hdr (enueue header), + * used to start an enqueue record in the journal. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_enq_hdr_hpp +#define mrg_journal_enq_hdr_hpp + +#include +#include "jrnl/rec_hdr.hpp" + +namespace mrg +{ +namespace journal +{ + +#pragma pack(1) + + /** + * \brief Struct for enqueue record. + * + * Struct for enqueue record. In addition to the common data, this header includes both the + * xid and data blob sizes. + * + * This header precedes all enqueue data in journal files. + * + * Record header info in binary format (32 bytes): + *
+    *   0                           7
+    * +---+---+---+---+---+---+---+---+  -+
+    * |     magic     | v | e | flags |   |
+    * +---+---+---+---+---+---+---+---+   | struct hdr
+    * |              rid              |   |
+    * +---+---+---+---+---+---+---+---+  -+
+    * |            xidsize            |
+    * +---+---+---+---+---+---+---+---+
+    * |             dsize             |
+    * +---+---+---+---+---+---+---+---+
+    * v = file version (If the format or encoding of this file changes, then this
+    *     number should be incremented)
+    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
+    * 
+ * + * Note that journal files should be transferable between 32- and 64-bit + * hardware of the same endianness, but not between hardware of opposite + * entianness without some sort of binary conversion utility. Thus buffering + * will be needed for types that change size between 32- and 64-bit compiles. + */ + struct enq_hdr : rec_hdr + { +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t +#endif + std::size_t _xidsize; ///< XID size +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t +#endif +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler1; ///< Big-endian filler for 32-bit size_t +#endif + std::size_t _dsize; ///< Record data size +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler1; ///< Little-endian filler for 32-bit size_t +#endif + static const u_int16_t ENQ_HDR_TRANSIENT_MASK = 0x10; + static const u_int16_t ENQ_HDR_EXTERNAL_MASK = 0x20; + + /** + * \brief Default constructor, which sets all values to 0. + */ + inline enq_hdr(): rec_hdr(), +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif + _xidsize(0), +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler1(0), +#endif + _dsize(0) +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + , _filler1(0) +#endif + {} + + /** + * \brief Convenience constructor which initializes values during construction. + */ + inline enq_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, + const std::size_t xidsize, const std::size_t dsize, const bool owi, + const bool transient = false): rec_hdr(magic, version, rid, owi), +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif + _xidsize(xidsize), +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler1(0), +#endif + _dsize(dsize) +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + , _filler1(0) +#endif + { set_transient(transient); } + + + inline bool is_transient() const { return _uflag & ENQ_HDR_TRANSIENT_MASK; } + + inline void set_transient(const bool transient) + { + _uflag = transient ? _uflag | ENQ_HDR_TRANSIENT_MASK : + _uflag & (~ENQ_HDR_TRANSIENT_MASK); + } + + inline bool is_external() const { return _uflag & ENQ_HDR_EXTERNAL_MASK; } + + inline void set_external(const bool external) + { + _uflag = external ? _uflag | ENQ_HDR_EXTERNAL_MASK : + _uflag & (~ENQ_HDR_EXTERNAL_MASK); + } + + /** + * \brief Returns the size of the header in bytes. + */ + inline static std::size_t size() { return sizeof(enq_hdr); } + }; + +#pragma pack() + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_enq_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/enq_hdr.hpp b/cpp/src/qpid/legacystore/jrnl/enq_hdr.hpp deleted file mode 100644 index a593db59c0..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/enq_hdr.hpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file enq_hdr.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::enq_hdr (enueue header), - * used to start an enqueue record in the journal. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_enq_hdr_hpp -#define mrg_journal_enq_hdr_hpp - -#include -#include "jrnl/rec_hdr.hpp" - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for enqueue record. - * - * Struct for enqueue record. In addition to the common data, this header includes both the - * xid and data blob sizes. - * - * This header precedes all enqueue data in journal files. - * - * Record header info in binary format (32 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+  -+
-    * |     magic     | v | e | flags |   |
-    * +---+---+---+---+---+---+---+---+   | struct hdr
-    * |              rid              |   |
-    * +---+---+---+---+---+---+---+---+  -+
-    * |            xidsize            |
-    * +---+---+---+---+---+---+---+---+
-    * |             dsize             |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct enq_hdr : rec_hdr - { -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _xidsize; ///< XID size -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler1; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _dsize; ///< Record data size -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler1; ///< Little-endian filler for 32-bit size_t -#endif - static const u_int16_t ENQ_HDR_TRANSIENT_MASK = 0x10; - static const u_int16_t ENQ_HDR_EXTERNAL_MASK = 0x20; - - /** - * \brief Default constructor, which sets all values to 0. - */ - inline enq_hdr(): rec_hdr(), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(0), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif - _dsize(0) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler1(0) -#endif - {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline enq_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const std::size_t xidsize, const std::size_t dsize, const bool owi, - const bool transient = false): rec_hdr(magic, version, rid, owi), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(xidsize), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif - _dsize(dsize) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler1(0) -#endif - { set_transient(transient); } - - - inline bool is_transient() const { return _uflag & ENQ_HDR_TRANSIENT_MASK; } - - inline void set_transient(const bool transient) - { - _uflag = transient ? _uflag | ENQ_HDR_TRANSIENT_MASK : - _uflag & (~ENQ_HDR_TRANSIENT_MASK); - } - - inline bool is_external() const { return _uflag & ENQ_HDR_EXTERNAL_MASK; } - - inline void set_external(const bool external) - { - _uflag = external ? _uflag | ENQ_HDR_EXTERNAL_MASK : - _uflag & (~ENQ_HDR_EXTERNAL_MASK); - } - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(enq_hdr); } - }; - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_enq_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/enq_map.h b/cpp/src/qpid/legacystore/jrnl/enq_map.h new file mode 100644 index 0000000000..34a802cfda --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/enq_map.h @@ -0,0 +1,127 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file enq_map.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::enq_map (enqueue map). + * See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_enq_map_hpp +#define mrg_journal_enq_map_hpp + +namespace mrg +{ +namespace journal +{ +class enq_map; +} +} + +#include "jrnl/jexception.hpp" +#include "jrnl/smutex.hpp" +#include +#include +#include + +namespace mrg +{ +namespace journal +{ + + /** + * \class enq_map + * \brief Class for storing the physical file id (pfid) and a transaction locked flag for each enqueued + * data block using the record id (rid) as a key. This is the primary mechanism for + * deterimining the enqueue low water mark: if a pfid exists in this map, then there is + * at least one still-enqueued record in that file. (The transaction map must also be + * clear, however.) + * + * Map rids against pfid and lock status. As records are enqueued, they are added to this + * map, and as they are dequeued, they are removed. An enqueue is locked when a transactional + * dequeue is pending that has been neither committed nor aborted. + *
+    *   key      data
+    *
+    *   rid1 --- [ pfid, txn_lock ]
+    *   rid2 --- [ pfid, txn_lock ]
+    *   rid3 --- [ pfid, txn_lock ]
+    *   ...
+    * 
+ */ + class enq_map + { + public: + // return/error codes + static int16_t EMAP_DUP_RID; + static int16_t EMAP_LOCKED; + static int16_t EMAP_RID_NOT_FOUND; + static int16_t EMAP_OK; + static int16_t EMAP_FALSE; + static int16_t EMAP_TRUE; + + private: + + struct emap_data_struct + { + u_int16_t _pfid; + bool _lock; + emap_data_struct(const u_int16_t pfid, const bool lock) : _pfid(pfid), _lock(lock) {} + }; + typedef std::pair emap_param; + typedef std::map emap; + typedef emap::iterator emap_itr; + + emap _map; + smutex _mutex; + std::vector _pfid_enq_cnt; + + public: + enq_map(); + virtual ~enq_map(); + + void set_num_jfiles(const u_int16_t num_jfiles); + inline u_int32_t get_enq_cnt(const u_int16_t pfid) const { return _pfid_enq_cnt.at(pfid); }; + + int16_t insert_pfid(const u_int64_t rid, const u_int16_t pfid); // 0=ok; -3=duplicate rid; + int16_t insert_pfid(const u_int64_t rid, const u_int16_t pfid, const bool locked); // 0=ok; -3=duplicate rid; + int16_t get_pfid(const u_int64_t rid); // >=0=pfid; -1=rid not found; -2=locked + int16_t get_remove_pfid(const u_int64_t rid, const bool txn_flag = false); // >=0=pfid; -1=rid not found; -2=locked + bool is_enqueued(const u_int64_t rid, bool ignore_lock = false); + int16_t lock(const u_int64_t rid); // 0=ok; -1=rid not found + int16_t unlock(const u_int64_t rid); // 0=ok; -1=rid not found + int16_t is_locked(const u_int64_t rid); // 1=true; 0=false; -1=rid not found + inline void clear() { _map.clear(); } + inline bool empty() const { return _map.empty(); } + inline u_int32_t size() const { return u_int32_t(_map.size()); } + void rid_list(std::vector& rv); + void pfid_list(std::vector& fv); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_enq_map_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/enq_map.hpp b/cpp/src/qpid/legacystore/jrnl/enq_map.hpp deleted file mode 100644 index 34a802cfda..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/enq_map.hpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file enq_map.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::enq_map (enqueue map). - * See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_enq_map_hpp -#define mrg_journal_enq_map_hpp - -namespace mrg -{ -namespace journal -{ -class enq_map; -} -} - -#include "jrnl/jexception.hpp" -#include "jrnl/smutex.hpp" -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class enq_map - * \brief Class for storing the physical file id (pfid) and a transaction locked flag for each enqueued - * data block using the record id (rid) as a key. This is the primary mechanism for - * deterimining the enqueue low water mark: if a pfid exists in this map, then there is - * at least one still-enqueued record in that file. (The transaction map must also be - * clear, however.) - * - * Map rids against pfid and lock status. As records are enqueued, they are added to this - * map, and as they are dequeued, they are removed. An enqueue is locked when a transactional - * dequeue is pending that has been neither committed nor aborted. - *
-    *   key      data
-    *
-    *   rid1 --- [ pfid, txn_lock ]
-    *   rid2 --- [ pfid, txn_lock ]
-    *   rid3 --- [ pfid, txn_lock ]
-    *   ...
-    * 
- */ - class enq_map - { - public: - // return/error codes - static int16_t EMAP_DUP_RID; - static int16_t EMAP_LOCKED; - static int16_t EMAP_RID_NOT_FOUND; - static int16_t EMAP_OK; - static int16_t EMAP_FALSE; - static int16_t EMAP_TRUE; - - private: - - struct emap_data_struct - { - u_int16_t _pfid; - bool _lock; - emap_data_struct(const u_int16_t pfid, const bool lock) : _pfid(pfid), _lock(lock) {} - }; - typedef std::pair emap_param; - typedef std::map emap; - typedef emap::iterator emap_itr; - - emap _map; - smutex _mutex; - std::vector _pfid_enq_cnt; - - public: - enq_map(); - virtual ~enq_map(); - - void set_num_jfiles(const u_int16_t num_jfiles); - inline u_int32_t get_enq_cnt(const u_int16_t pfid) const { return _pfid_enq_cnt.at(pfid); }; - - int16_t insert_pfid(const u_int64_t rid, const u_int16_t pfid); // 0=ok; -3=duplicate rid; - int16_t insert_pfid(const u_int64_t rid, const u_int16_t pfid, const bool locked); // 0=ok; -3=duplicate rid; - int16_t get_pfid(const u_int64_t rid); // >=0=pfid; -1=rid not found; -2=locked - int16_t get_remove_pfid(const u_int64_t rid, const bool txn_flag = false); // >=0=pfid; -1=rid not found; -2=locked - bool is_enqueued(const u_int64_t rid, bool ignore_lock = false); - int16_t lock(const u_int64_t rid); // 0=ok; -1=rid not found - int16_t unlock(const u_int64_t rid); // 0=ok; -1=rid not found - int16_t is_locked(const u_int64_t rid); // 1=true; 0=false; -1=rid not found - inline void clear() { _map.clear(); } - inline bool empty() const { return _map.empty(); } - inline u_int32_t size() const { return u_int32_t(_map.size()); } - void rid_list(std::vector& rv); - void pfid_list(std::vector& fv); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_enq_map_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/enq_rec.h b/cpp/src/qpid/legacystore/jrnl/enq_rec.h new file mode 100644 index 0000000000..ce3d881d4e --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/enq_rec.h @@ -0,0 +1,116 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file enq_rec.hpp + * + * Qpid asynchronous store plugin library + * + * This file contains the code for the mrg::journal::enq_rec (journal enqueue + * record) class. See class documentation for details. + */ + +#ifndef mrg_journal_enq_rec_hpp +#define mrg_journal_enq_rec_hpp + +namespace mrg +{ +namespace journal +{ +class enq_rec; +} +} + +#include +#include "jrnl/enq_hdr.hpp" +#include "jrnl/jrec.hpp" + +namespace mrg +{ +namespace journal +{ + + /** + * \class enq_rec + * \brief Class to handle a single journal enqueue record. + */ + class enq_rec : public jrec + { + private: + enq_hdr _enq_hdr; + const void* _xidp; ///< xid pointer for encoding (for writing to disk) + const void* _data; ///< Pointer to data to be written to disk + void* _buff; ///< Pointer to buffer to receive data read from disk + rec_tail _enq_tail; + + public: + /** + * \brief Constructor used for read operations. + */ + enq_rec(); + + /** + * \brief Constructor used for write operations, where mbuf contains data to be written. + */ + enq_rec(const u_int64_t rid, const void* const dbuf, const std::size_t dlen, + const void* const xidp, const std::size_t xidlen, const bool owi, const bool transient); + + /** + * \brief Destructor + */ + virtual ~enq_rec(); + + // Prepare instance for use in reading data from journal, xid and data will be allocated + void reset(); + // Prepare instance for use in writing data to journal + void reset(const u_int64_t rid, const void* const dbuf, const std::size_t dlen, + const void* const xidp, const std::size_t xidlen, const bool owi, const bool transient, + const bool external); + + u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks); + u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, + u_int32_t max_size_dblks); + // Decode used for recover + bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs); + + std::size_t get_xid(void** const xidpp); + std::size_t get_data(void** const datapp); + inline bool is_transient() const { return _enq_hdr.is_transient(); } + inline bool is_external() const { return _enq_hdr.is_external(); } + std::string& str(std::string& str) const; + inline std::size_t data_size() const { return _enq_hdr._dsize; } + inline std::size_t xid_size() const { return _enq_hdr._xidsize; } + std::size_t rec_size() const; + static std::size_t rec_size(const std::size_t xidsize, const std::size_t dsize, const bool external); + inline u_int64_t rid() const { return _enq_hdr._rid; } + void set_rid(const u_int64_t rid); + + private: + void chk_hdr() const; + void chk_hdr(u_int64_t rid) const; + void chk_tail() const; + virtual void clean(); + }; // class enq_rec + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_enq_rec_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/enq_rec.hpp b/cpp/src/qpid/legacystore/jrnl/enq_rec.hpp deleted file mode 100644 index ce3d881d4e..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/enq_rec.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file enq_rec.hpp - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::enq_rec (journal enqueue - * record) class. See class documentation for details. - */ - -#ifndef mrg_journal_enq_rec_hpp -#define mrg_journal_enq_rec_hpp - -namespace mrg -{ -namespace journal -{ -class enq_rec; -} -} - -#include -#include "jrnl/enq_hdr.hpp" -#include "jrnl/jrec.hpp" - -namespace mrg -{ -namespace journal -{ - - /** - * \class enq_rec - * \brief Class to handle a single journal enqueue record. - */ - class enq_rec : public jrec - { - private: - enq_hdr _enq_hdr; - const void* _xidp; ///< xid pointer for encoding (for writing to disk) - const void* _data; ///< Pointer to data to be written to disk - void* _buff; ///< Pointer to buffer to receive data read from disk - rec_tail _enq_tail; - - public: - /** - * \brief Constructor used for read operations. - */ - enq_rec(); - - /** - * \brief Constructor used for write operations, where mbuf contains data to be written. - */ - enq_rec(const u_int64_t rid, const void* const dbuf, const std::size_t dlen, - const void* const xidp, const std::size_t xidlen, const bool owi, const bool transient); - - /** - * \brief Destructor - */ - virtual ~enq_rec(); - - // Prepare instance for use in reading data from journal, xid and data will be allocated - void reset(); - // Prepare instance for use in writing data to journal - void reset(const u_int64_t rid, const void* const dbuf, const std::size_t dlen, - const void* const xidp, const std::size_t xidlen, const bool owi, const bool transient, - const bool external); - - u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks); - u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks); - // Decode used for recover - bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs); - - std::size_t get_xid(void** const xidpp); - std::size_t get_data(void** const datapp); - inline bool is_transient() const { return _enq_hdr.is_transient(); } - inline bool is_external() const { return _enq_hdr.is_external(); } - std::string& str(std::string& str) const; - inline std::size_t data_size() const { return _enq_hdr._dsize; } - inline std::size_t xid_size() const { return _enq_hdr._xidsize; } - std::size_t rec_size() const; - static std::size_t rec_size(const std::size_t xidsize, const std::size_t dsize, const bool external); - inline u_int64_t rid() const { return _enq_hdr._rid; } - void set_rid(const u_int64_t rid); - - private: - void chk_hdr() const; - void chk_hdr(u_int64_t rid) const; - void chk_tail() const; - virtual void clean(); - }; // class enq_rec - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_enq_rec_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/enums.h b/cpp/src/qpid/legacystore/jrnl/enums.h new file mode 100644 index 0000000000..8dade01aa3 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/enums.h @@ -0,0 +1,108 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file enums.hpp + * + * Qpid asynchronous store plugin library + * + * File containing definitions for namespace mrg::journal enums. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_enums_hpp +#define mrg_journal_enums_hpp + +namespace mrg +{ +namespace journal +{ + + // TODO: Change this to flags, as multiple of these conditions may exist simultaneously + /** + * \brief Enumeration of possilbe return states from journal read and write operations. + */ + enum _iores + { + RHM_IORES_SUCCESS = 0, ///< Success: IO operation completed noramlly. + RHM_IORES_PAGE_AIOWAIT, ///< IO operation suspended - next page is waiting for AIO. + RHM_IORES_FILE_AIOWAIT, ///< IO operation suspended - next file is waiting for AIO. + RHM_IORES_EMPTY, ///< During read operations, nothing further is available to read. + RHM_IORES_RCINVALID, ///< Read page cache is invalid (ie obsolete or uninitialized) + RHM_IORES_ENQCAPTHRESH, ///< Enqueue capacity threshold (limit) reached. + RHM_IORES_FULL, ///< During write operations, the journal files are full. + RHM_IORES_BUSY, ///< Another blocking operation is in progress. + RHM_IORES_TXPENDING, ///< Operation blocked by pending transaction. + RHM_IORES_NOTIMPL ///< Function is not yet implemented. + }; + typedef _iores iores; + + static inline const char* iores_str(iores res) + { + switch (res) + { + case RHM_IORES_SUCCESS: return "RHM_IORES_SUCCESS"; + case RHM_IORES_PAGE_AIOWAIT: return "RHM_IORES_PAGE_AIOWAIT"; + case RHM_IORES_FILE_AIOWAIT: return "RHM_IORES_FILE_AIOWAIT"; + case RHM_IORES_EMPTY: return "RHM_IORES_EMPTY"; + case RHM_IORES_RCINVALID: return "RHM_IORES_RCINVALID"; + case RHM_IORES_ENQCAPTHRESH: return "RHM_IORES_ENQCAPTHRESH"; + case RHM_IORES_FULL: return "RHM_IORES_FULL"; + case RHM_IORES_BUSY: return "RHM_IORES_BUSY"; + case RHM_IORES_TXPENDING: return "RHM_IORES_TXPENDING"; + case RHM_IORES_NOTIMPL: return "RHM_IORES_NOTIMPL"; + } + return ""; + } + + enum _log_level + { + LOG_TRACE = 0, + LOG_DEBUG, + LOG_INFO, + LOG_NOTICE, + LOG_WARN, + LOG_ERROR, + LOG_CRITICAL + }; + typedef _log_level log_level; + + static inline const char* log_level_str(log_level ll) + { + switch (ll) + { + case LOG_TRACE: return "TRACE"; + case LOG_DEBUG: return "DEBUG"; + case LOG_INFO: return "INFO"; + case LOG_NOTICE: return "NOTICE"; + case LOG_WARN: return "WARN"; + case LOG_ERROR: return "ERROR"; + case LOG_CRITICAL: return "CRITICAL"; + } + return ""; + } + + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_enums_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/enums.hpp b/cpp/src/qpid/legacystore/jrnl/enums.hpp deleted file mode 100644 index 8dade01aa3..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/enums.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file enums.hpp - * - * Qpid asynchronous store plugin library - * - * File containing definitions for namespace mrg::journal enums. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_enums_hpp -#define mrg_journal_enums_hpp - -namespace mrg -{ -namespace journal -{ - - // TODO: Change this to flags, as multiple of these conditions may exist simultaneously - /** - * \brief Enumeration of possilbe return states from journal read and write operations. - */ - enum _iores - { - RHM_IORES_SUCCESS = 0, ///< Success: IO operation completed noramlly. - RHM_IORES_PAGE_AIOWAIT, ///< IO operation suspended - next page is waiting for AIO. - RHM_IORES_FILE_AIOWAIT, ///< IO operation suspended - next file is waiting for AIO. - RHM_IORES_EMPTY, ///< During read operations, nothing further is available to read. - RHM_IORES_RCINVALID, ///< Read page cache is invalid (ie obsolete or uninitialized) - RHM_IORES_ENQCAPTHRESH, ///< Enqueue capacity threshold (limit) reached. - RHM_IORES_FULL, ///< During write operations, the journal files are full. - RHM_IORES_BUSY, ///< Another blocking operation is in progress. - RHM_IORES_TXPENDING, ///< Operation blocked by pending transaction. - RHM_IORES_NOTIMPL ///< Function is not yet implemented. - }; - typedef _iores iores; - - static inline const char* iores_str(iores res) - { - switch (res) - { - case RHM_IORES_SUCCESS: return "RHM_IORES_SUCCESS"; - case RHM_IORES_PAGE_AIOWAIT: return "RHM_IORES_PAGE_AIOWAIT"; - case RHM_IORES_FILE_AIOWAIT: return "RHM_IORES_FILE_AIOWAIT"; - case RHM_IORES_EMPTY: return "RHM_IORES_EMPTY"; - case RHM_IORES_RCINVALID: return "RHM_IORES_RCINVALID"; - case RHM_IORES_ENQCAPTHRESH: return "RHM_IORES_ENQCAPTHRESH"; - case RHM_IORES_FULL: return "RHM_IORES_FULL"; - case RHM_IORES_BUSY: return "RHM_IORES_BUSY"; - case RHM_IORES_TXPENDING: return "RHM_IORES_TXPENDING"; - case RHM_IORES_NOTIMPL: return "RHM_IORES_NOTIMPL"; - } - return ""; - } - - enum _log_level - { - LOG_TRACE = 0, - LOG_DEBUG, - LOG_INFO, - LOG_NOTICE, - LOG_WARN, - LOG_ERROR, - LOG_CRITICAL - }; - typedef _log_level log_level; - - static inline const char* log_level_str(log_level ll) - { - switch (ll) - { - case LOG_TRACE: return "TRACE"; - case LOG_DEBUG: return "DEBUG"; - case LOG_INFO: return "INFO"; - case LOG_NOTICE: return "NOTICE"; - case LOG_WARN: return "WARN"; - case LOG_ERROR: return "ERROR"; - case LOG_CRITICAL: return "CRITICAL"; - } - return ""; - } - - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_enums_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/fcntl.h b/cpp/src/qpid/legacystore/jrnl/fcntl.h new file mode 100644 index 0000000000..a7b28b2fe9 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/fcntl.h @@ -0,0 +1,156 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file fcntl.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::fcntl (non-logging file + * handle), used for controlling journal log files. See class documentation for + * details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_fcntl_hpp +#define mrg_journal_fcntl_hpp + +namespace mrg +{ +namespace journal +{ +class fcntl; +} +} + +#include +#include +#include "jrnl/rcvdat.hpp" +#include + +namespace mrg +{ +namespace journal +{ + + /** + * \class fcntl + * \brief Journal file controller. There is one instance per journal file. + */ + class fcntl + { + protected: + std::string _fname; ///< File name + u_int16_t _pfid; ///< Physical file ID (file number in order of creation) + u_int16_t _lfid; ///< Logical file ID (ordinal number in ring store) + const u_int32_t _ffull_dblks; ///< File size in dblks (incl. file header) + int _wr_fh; ///< Write file handle + u_int32_t _rec_enqcnt; ///< Count of enqueued records + u_int32_t _rd_subm_cnt_dblks; ///< Read file count (data blocks) for submitted AIO + u_int32_t _rd_cmpl_cnt_dblks; ///< Read file count (data blocks) for completed AIO + u_int32_t _wr_subm_cnt_dblks; ///< Write file count (data blocks) for submitted AIO + u_int32_t _wr_cmpl_cnt_dblks; ///< Write file count (data blocks) for completed AIO + u_int16_t _aio_cnt; ///< Outstanding AIO operations on this file + bool _fhdr_wr_aio_outstanding; ///< Outstanding file header write on this file + + public: + // Constructors with implicit initialize() and open() + fcntl(const std::string& fbasename, const u_int16_t pfid, const u_int16_t lfid, const u_int32_t jfsize_sblks, + const rcvdat* const ro); + virtual ~fcntl(); + + virtual bool reset(const rcvdat* const ro = 0); + virtual void rd_reset(); + virtual bool wr_reset(const rcvdat* const ro = 0); + + virtual int open_wr_fh(); + virtual void close_wr_fh(); + inline bool is_wr_fh_open() const { return _wr_fh >= 0; } + + inline const std::string& fname() const { return _fname; } + inline u_int16_t pfid() const { return _pfid; } + inline u_int16_t lfid() const { return _lfid; } + inline void set_lfid(const u_int16_t lfid) { _lfid = lfid; } + inline int wr_fh() const { return _wr_fh; } + inline u_int32_t enqcnt() const { return _rec_enqcnt; } + inline u_int32_t incr_enqcnt() { return ++_rec_enqcnt; } + u_int32_t add_enqcnt(u_int32_t a); + u_int32_t decr_enqcnt(); + u_int32_t subtr_enqcnt(u_int32_t s); + + inline u_int32_t rd_subm_cnt_dblks() const { return _rd_subm_cnt_dblks; } + inline std::size_t rd_subm_offs() const { return _rd_subm_cnt_dblks * JRNL_DBLK_SIZE; } + u_int32_t add_rd_subm_cnt_dblks(u_int32_t a); + + inline u_int32_t rd_cmpl_cnt_dblks() const { return _rd_cmpl_cnt_dblks; } + inline std::size_t rd_cmpl_offs() const { return _rd_cmpl_cnt_dblks * JRNL_DBLK_SIZE; } + u_int32_t add_rd_cmpl_cnt_dblks(u_int32_t a); + + inline u_int32_t wr_subm_cnt_dblks() const { return _wr_subm_cnt_dblks; } + inline std::size_t wr_subm_offs() const { return _wr_subm_cnt_dblks * JRNL_DBLK_SIZE; } + u_int32_t add_wr_subm_cnt_dblks(u_int32_t a); + + inline u_int32_t wr_cmpl_cnt_dblks() const { return _wr_cmpl_cnt_dblks; } + inline std::size_t wr_cmpl_offs() const { return _wr_cmpl_cnt_dblks * JRNL_DBLK_SIZE; } + u_int32_t add_wr_cmpl_cnt_dblks(u_int32_t a); + + inline u_int16_t aio_cnt() const { return _aio_cnt; } + inline u_int16_t incr_aio_cnt() { return ++_aio_cnt; } + u_int16_t decr_aio_cnt(); + + inline bool wr_fhdr_aio_outstanding() { return _fhdr_wr_aio_outstanding; } + inline void set_wr_fhdr_aio_outstanding(const bool wfao) { _fhdr_wr_aio_outstanding = wfao; } + + // Derived helper functions + + inline bool rd_void() const { return _wr_cmpl_cnt_dblks == 0; } + inline bool rd_empty() const { return _wr_cmpl_cnt_dblks <= JRNL_SBLK_SIZE; } + inline u_int32_t rd_remaining_dblks() const { return _wr_cmpl_cnt_dblks - _rd_subm_cnt_dblks; } + inline bool is_rd_full() const { return _wr_cmpl_cnt_dblks == _rd_subm_cnt_dblks; } + inline bool is_rd_compl() const { return _wr_cmpl_cnt_dblks == _rd_cmpl_cnt_dblks; } + inline u_int32_t rd_aio_outstanding_dblks() const { return _rd_subm_cnt_dblks - _rd_cmpl_cnt_dblks; } + inline bool rd_file_rotate() const { return is_rd_full() && is_wr_compl(); } + + inline bool wr_void() const { return _wr_subm_cnt_dblks == 0; } + inline bool wr_empty() const { return _wr_subm_cnt_dblks <= JRNL_SBLK_SIZE; } + inline u_int32_t wr_remaining_dblks() const { return _ffull_dblks - _wr_subm_cnt_dblks; } + inline bool is_wr_full() const { return _ffull_dblks == _wr_subm_cnt_dblks; } + inline bool is_wr_compl() const { return _ffull_dblks == _wr_cmpl_cnt_dblks; } + inline u_int32_t wr_aio_outstanding_dblks() const { return _wr_subm_cnt_dblks - _wr_cmpl_cnt_dblks; } + inline bool wr_file_rotate() const { return is_wr_full(); } + + // Debug aid + const std::string status_str() const; + + protected: + virtual void initialize(const std::string& fbasename, const u_int16_t pfid, const u_int16_t lfid, + const u_int32_t jfsize_sblks, const rcvdat* const ro); + + static std::string filename(const std::string& fbasename, const u_int16_t pfid); + void clean_file(const u_int32_t jfsize_sblks); + void create_jfile(const u_int32_t jfsize_sblks); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_fcntl_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/fcntl.hpp b/cpp/src/qpid/legacystore/jrnl/fcntl.hpp deleted file mode 100644 index a7b28b2fe9..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/fcntl.hpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file fcntl.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::fcntl (non-logging file - * handle), used for controlling journal log files. See class documentation for - * details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_fcntl_hpp -#define mrg_journal_fcntl_hpp - -namespace mrg -{ -namespace journal -{ -class fcntl; -} -} - -#include -#include -#include "jrnl/rcvdat.hpp" -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class fcntl - * \brief Journal file controller. There is one instance per journal file. - */ - class fcntl - { - protected: - std::string _fname; ///< File name - u_int16_t _pfid; ///< Physical file ID (file number in order of creation) - u_int16_t _lfid; ///< Logical file ID (ordinal number in ring store) - const u_int32_t _ffull_dblks; ///< File size in dblks (incl. file header) - int _wr_fh; ///< Write file handle - u_int32_t _rec_enqcnt; ///< Count of enqueued records - u_int32_t _rd_subm_cnt_dblks; ///< Read file count (data blocks) for submitted AIO - u_int32_t _rd_cmpl_cnt_dblks; ///< Read file count (data blocks) for completed AIO - u_int32_t _wr_subm_cnt_dblks; ///< Write file count (data blocks) for submitted AIO - u_int32_t _wr_cmpl_cnt_dblks; ///< Write file count (data blocks) for completed AIO - u_int16_t _aio_cnt; ///< Outstanding AIO operations on this file - bool _fhdr_wr_aio_outstanding; ///< Outstanding file header write on this file - - public: - // Constructors with implicit initialize() and open() - fcntl(const std::string& fbasename, const u_int16_t pfid, const u_int16_t lfid, const u_int32_t jfsize_sblks, - const rcvdat* const ro); - virtual ~fcntl(); - - virtual bool reset(const rcvdat* const ro = 0); - virtual void rd_reset(); - virtual bool wr_reset(const rcvdat* const ro = 0); - - virtual int open_wr_fh(); - virtual void close_wr_fh(); - inline bool is_wr_fh_open() const { return _wr_fh >= 0; } - - inline const std::string& fname() const { return _fname; } - inline u_int16_t pfid() const { return _pfid; } - inline u_int16_t lfid() const { return _lfid; } - inline void set_lfid(const u_int16_t lfid) { _lfid = lfid; } - inline int wr_fh() const { return _wr_fh; } - inline u_int32_t enqcnt() const { return _rec_enqcnt; } - inline u_int32_t incr_enqcnt() { return ++_rec_enqcnt; } - u_int32_t add_enqcnt(u_int32_t a); - u_int32_t decr_enqcnt(); - u_int32_t subtr_enqcnt(u_int32_t s); - - inline u_int32_t rd_subm_cnt_dblks() const { return _rd_subm_cnt_dblks; } - inline std::size_t rd_subm_offs() const { return _rd_subm_cnt_dblks * JRNL_DBLK_SIZE; } - u_int32_t add_rd_subm_cnt_dblks(u_int32_t a); - - inline u_int32_t rd_cmpl_cnt_dblks() const { return _rd_cmpl_cnt_dblks; } - inline std::size_t rd_cmpl_offs() const { return _rd_cmpl_cnt_dblks * JRNL_DBLK_SIZE; } - u_int32_t add_rd_cmpl_cnt_dblks(u_int32_t a); - - inline u_int32_t wr_subm_cnt_dblks() const { return _wr_subm_cnt_dblks; } - inline std::size_t wr_subm_offs() const { return _wr_subm_cnt_dblks * JRNL_DBLK_SIZE; } - u_int32_t add_wr_subm_cnt_dblks(u_int32_t a); - - inline u_int32_t wr_cmpl_cnt_dblks() const { return _wr_cmpl_cnt_dblks; } - inline std::size_t wr_cmpl_offs() const { return _wr_cmpl_cnt_dblks * JRNL_DBLK_SIZE; } - u_int32_t add_wr_cmpl_cnt_dblks(u_int32_t a); - - inline u_int16_t aio_cnt() const { return _aio_cnt; } - inline u_int16_t incr_aio_cnt() { return ++_aio_cnt; } - u_int16_t decr_aio_cnt(); - - inline bool wr_fhdr_aio_outstanding() { return _fhdr_wr_aio_outstanding; } - inline void set_wr_fhdr_aio_outstanding(const bool wfao) { _fhdr_wr_aio_outstanding = wfao; } - - // Derived helper functions - - inline bool rd_void() const { return _wr_cmpl_cnt_dblks == 0; } - inline bool rd_empty() const { return _wr_cmpl_cnt_dblks <= JRNL_SBLK_SIZE; } - inline u_int32_t rd_remaining_dblks() const { return _wr_cmpl_cnt_dblks - _rd_subm_cnt_dblks; } - inline bool is_rd_full() const { return _wr_cmpl_cnt_dblks == _rd_subm_cnt_dblks; } - inline bool is_rd_compl() const { return _wr_cmpl_cnt_dblks == _rd_cmpl_cnt_dblks; } - inline u_int32_t rd_aio_outstanding_dblks() const { return _rd_subm_cnt_dblks - _rd_cmpl_cnt_dblks; } - inline bool rd_file_rotate() const { return is_rd_full() && is_wr_compl(); } - - inline bool wr_void() const { return _wr_subm_cnt_dblks == 0; } - inline bool wr_empty() const { return _wr_subm_cnt_dblks <= JRNL_SBLK_SIZE; } - inline u_int32_t wr_remaining_dblks() const { return _ffull_dblks - _wr_subm_cnt_dblks; } - inline bool is_wr_full() const { return _ffull_dblks == _wr_subm_cnt_dblks; } - inline bool is_wr_compl() const { return _ffull_dblks == _wr_cmpl_cnt_dblks; } - inline u_int32_t wr_aio_outstanding_dblks() const { return _wr_subm_cnt_dblks - _wr_cmpl_cnt_dblks; } - inline bool wr_file_rotate() const { return is_wr_full(); } - - // Debug aid - const std::string status_str() const; - - protected: - virtual void initialize(const std::string& fbasename, const u_int16_t pfid, const u_int16_t lfid, - const u_int32_t jfsize_sblks, const rcvdat* const ro); - - static std::string filename(const std::string& fbasename, const u_int16_t pfid); - void clean_file(const u_int32_t jfsize_sblks); - void create_jfile(const u_int32_t jfsize_sblks); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_fcntl_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/file_hdr.h b/cpp/src/qpid/legacystore/jrnl/file_hdr.h new file mode 100644 index 0000000000..4466ef5617 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/file_hdr.h @@ -0,0 +1,211 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file file_hdr.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::file_hdr (file + * record header), used to start a journal file. It contains some + * file metadata and information to aid journal recovery. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_file_hdr_hpp +#define mrg_journal_file_hdr_hpp + +#include +#include +#include "jrnl/rec_hdr.hpp" +#include "jrnl/jerrno.hpp" +#include "jrnl/jexception.hpp" +#include + +namespace mrg +{ +namespace journal +{ + +#pragma pack(1) + + /** + * \brief Struct for data common to the head of all journal files. In addition to + * the common data, this includes the record ID and offset of the first record in + * the file. + * + * This header precedes all data in journal files and occupies the first complete + * block in the file. The record ID and offset are updated on each overwrite of the + * file. + * + * File header info in binary format (48 bytes): + *
+    *   0                           7
+    * +---+---+---+---+---+---+---+---+  -+
+    * |     magic     | v | e | flags |   |
+    * +---+---+---+---+---+---+---+---+   | struct hdr
+    * |       first rid in file       |   |
+    * +---+---+---+---+---+---+---+---+  -+
+    * | pfid  | lfid  |  reserved (0) |
+    * +---+---+---+---+---+---+---+---+
+    * |              fro              |
+    * +---+---+---+---+---+---+---+---+
+    * |           timestamp (sec)     |
+    * +---+---+---+---+---+---+---+---+
+    * |           timestamp (ns)      |
+    * +---+---+---+---+---+---+---+---+
+    * v = file version (If the format or encoding of this file changes, then this
+    *     number should be incremented)
+    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
+    * pfid = File ID (number used in naming file)
+    * lfid = Logical ID (order used in circular buffer)
+    * fro = First record offset, offset from start of file to first record header
+    * 
+ * + * Note that journal files should be transferable between 32- and 64-bit + * hardware of the same endianness, but not between hardware of opposite + * entianness without some sort of binary conversion utility. Thus buffering + * will be needed for types that change size between 32- and 64-bit compiles. + */ + struct file_hdr : rec_hdr + { + u_int16_t _pfid; ///< Physical file ID (pfid) + u_int16_t _lfid; ///< Logical file ID (lfid) + u_int32_t _res; ///< Reserved (for alignment/flags) +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t +#endif + std::size_t _fro; ///< First record offset +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t +#endif +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler1; ///< Big-endian filler for 32-bit time_t +#endif + std::time_t _ts_sec; ///< Timestamp of journal initilailization +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler1; ///< Little-endian filler for 32-bit time_t +#endif +#if defined(JRNL_BIG_ENDIAN) + u_int32_t _filler2; ///< Big endian filler for u_int32_t +#endif + u_int32_t _ts_nsec; ///< Timestamp of journal initilailization +#if defined(JRNL_LITTLE_ENDIAN) + u_int32_t _filler2; ///< Little-endian filler for u_int32_t +#endif + + /** + * \brief Default constructor, which sets all values to 0. + */ + inline file_hdr(): rec_hdr(), _pfid(0), _lfid(0), _res(0), +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif + _fro(0), +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler1(0), +#endif + _ts_sec(0), +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + _filler1(0), +#endif +#if defined(JRNL_BIG_ENDIAN) + _filler2(0), +#endif + _ts_nsec(0) +#if defined(JRNL_LITTLE_ENDIAN) + , _filler2(0) +#endif + {} + + /** + * \brief Convenience constructor which initializes values during construction. + */ + inline file_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, + const u_int16_t pfid, const u_int16_t lfid, const std::size_t fro, + const bool owi, const bool settime = false): + rec_hdr(magic, version, rid, owi), _pfid(pfid), _lfid(lfid), _res(0), +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif + _fro(fro), +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler1(0), +#endif + _ts_sec(0), +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + _filler1(0), +#endif +#if defined(JRNL_BIG_ENDIAN) + _filler2(0), +#endif + _ts_nsec(0) +#if defined(JRNL_LITTLE_ENDIAN) + , _filler2(0) +#endif + { if (settime) set_time(); } + + /** + * \brief Gets the current time from the system clock and sets the timestamp in the struct. + */ + inline void set_time() + { + // TODO: Standardize on method for getting time that does not requrie a context switch. + timespec ts; + if (::clock_gettime(CLOCK_REALTIME, &ts)) + { + std::ostringstream oss; + oss << FORMAT_SYSERR(errno); + throw jexception(jerrno::JERR__RTCLOCK, oss.str(), "file_hdr", "set_time"); + } + _ts_sec = ts.tv_sec; + _ts_nsec = ts.tv_nsec; + } + + /** + * \brief Sets the timestamp in the struct to the provided value (in seconds and + * nanoseconds). + */ + inline void set_time(timespec& ts) + { + _ts_sec = ts.tv_sec; + _ts_nsec = ts.tv_nsec; + } + + /** + * \brief Returns the size of the header in bytes. + */ + inline static std::size_t size() { return sizeof(file_hdr); } + }; // struct file_hdr + +#pragma pack() + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_file_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/file_hdr.hpp b/cpp/src/qpid/legacystore/jrnl/file_hdr.hpp deleted file mode 100644 index 4466ef5617..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/file_hdr.hpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file file_hdr.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::file_hdr (file - * record header), used to start a journal file. It contains some - * file metadata and information to aid journal recovery. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_file_hdr_hpp -#define mrg_journal_file_hdr_hpp - -#include -#include -#include "jrnl/rec_hdr.hpp" -#include "jrnl/jerrno.hpp" -#include "jrnl/jexception.hpp" -#include - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for data common to the head of all journal files. In addition to - * the common data, this includes the record ID and offset of the first record in - * the file. - * - * This header precedes all data in journal files and occupies the first complete - * block in the file. The record ID and offset are updated on each overwrite of the - * file. - * - * File header info in binary format (48 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+  -+
-    * |     magic     | v | e | flags |   |
-    * +---+---+---+---+---+---+---+---+   | struct hdr
-    * |       first rid in file       |   |
-    * +---+---+---+---+---+---+---+---+  -+
-    * | pfid  | lfid  |  reserved (0) |
-    * +---+---+---+---+---+---+---+---+
-    * |              fro              |
-    * +---+---+---+---+---+---+---+---+
-    * |           timestamp (sec)     |
-    * +---+---+---+---+---+---+---+---+
-    * |           timestamp (ns)      |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * pfid = File ID (number used in naming file)
-    * lfid = Logical ID (order used in circular buffer)
-    * fro = First record offset, offset from start of file to first record header
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct file_hdr : rec_hdr - { - u_int16_t _pfid; ///< Physical file ID (pfid) - u_int16_t _lfid; ///< Logical file ID (lfid) - u_int32_t _res; ///< Reserved (for alignment/flags) -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _fro; ///< First record offset -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler1; ///< Big-endian filler for 32-bit time_t -#endif - std::time_t _ts_sec; ///< Timestamp of journal initilailization -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler1; ///< Little-endian filler for 32-bit time_t -#endif -#if defined(JRNL_BIG_ENDIAN) - u_int32_t _filler2; ///< Big endian filler for u_int32_t -#endif - u_int32_t _ts_nsec; ///< Timestamp of journal initilailization -#if defined(JRNL_LITTLE_ENDIAN) - u_int32_t _filler2; ///< Little-endian filler for u_int32_t -#endif - - /** - * \brief Default constructor, which sets all values to 0. - */ - inline file_hdr(): rec_hdr(), _pfid(0), _lfid(0), _res(0), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _fro(0), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif - _ts_sec(0), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif -#if defined(JRNL_BIG_ENDIAN) - _filler2(0), -#endif - _ts_nsec(0) -#if defined(JRNL_LITTLE_ENDIAN) - , _filler2(0) -#endif - {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline file_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const u_int16_t pfid, const u_int16_t lfid, const std::size_t fro, - const bool owi, const bool settime = false): - rec_hdr(magic, version, rid, owi), _pfid(pfid), _lfid(lfid), _res(0), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _fro(fro), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif - _ts_sec(0), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif -#if defined(JRNL_BIG_ENDIAN) - _filler2(0), -#endif - _ts_nsec(0) -#if defined(JRNL_LITTLE_ENDIAN) - , _filler2(0) -#endif - { if (settime) set_time(); } - - /** - * \brief Gets the current time from the system clock and sets the timestamp in the struct. - */ - inline void set_time() - { - // TODO: Standardize on method for getting time that does not requrie a context switch. - timespec ts; - if (::clock_gettime(CLOCK_REALTIME, &ts)) - { - std::ostringstream oss; - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__RTCLOCK, oss.str(), "file_hdr", "set_time"); - } - _ts_sec = ts.tv_sec; - _ts_nsec = ts.tv_nsec; - } - - /** - * \brief Sets the timestamp in the struct to the provided value (in seconds and - * nanoseconds). - */ - inline void set_time(timespec& ts) - { - _ts_sec = ts.tv_sec; - _ts_nsec = ts.tv_nsec; - } - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(file_hdr); } - }; // struct file_hdr - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_file_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jcfg.h b/cpp/src/qpid/legacystore/jrnl/jcfg.h new file mode 100644 index 0000000000..183223fe7f --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/jcfg.h @@ -0,0 +1,91 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file jcfg.hpp + * + * Qpid asynchronous store plugin library + * + * This file contains \#defines that control the implementation details of + * the journal. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_jcfg_hpp +#define mrg_journal_jcfg_hpp + +#if defined(__i386__) /* little endian, 32 bits */ +#define JRNL_LITTLE_ENDIAN +#define JRNL_32_BIT +#elif defined(__PPC__) || defined(__s390__) /* big endian, 32 bits */ +#define JRNL_BIG_ENDIAN +#define JRNL_32_BIT +#elif defined(__ia64__) || defined(__x86_64__) || defined(__alpha__) /* little endian, 64 bits */ +#define JRNL_LITTLE_ENDIAN +#define JRNL_64_BIT +#elif defined(__powerpc64__) || defined(__s390x__) /* big endian, 64 bits */ +#define JRNL_BIG_ENDIAN +#define JRNL_64_BIT +#else +#error endian? +#endif + + +/** +* Rule: Data block size (JRNL_DBLK_SIZE) MUST be a power of 2 such that +*
+* JRNL_DBLK_SIZE * JRNL_SBLK_SIZE == n * 512 (n = 1,2,3...)
+* 
+* (The disk softblock size is 512 for Linux kernels >= 2.6) +*/ +#define JRNL_DBLK_SIZE 128 ///< Data block size in bytes (CANNOT BE LESS THAN 32!) +#define JRNL_SBLK_SIZE 4 ///< Disk softblock size in multiples of JRNL_DBLK_SIZE +#define JRNL_MIN_FILE_SIZE 128 ///< Min. jrnl file size in sblks (excl. file_hdr) +#define JRNL_MAX_FILE_SIZE 4194176 ///< Max. jrnl file size in sblks (excl. file_hdr) +#define JRNL_MIN_NUM_FILES 4 ///< Min. number of journal files +#define JRNL_MAX_NUM_FILES 64 ///< Max. number of journal files +#define JRNL_ENQ_THRESHOLD 80 ///< Percent full when enqueue connection will be closed + +#define JRNL_RMGR_PAGE_SIZE 128 ///< Journal page size in softblocks +#define JRNL_RMGR_PAGES 16 ///< Number of pages to use in wmgr + +#define JRNL_WMGR_DEF_PAGE_SIZE 64 ///< Journal write page size in softblocks (default) +#define JRNL_WMGR_DEF_PAGES 32 ///< Number of pages to use in wmgr (default) + +#define JRNL_WMGR_MAXDTOKPP 1024 ///< Max. dtoks (data blocks) per page in wmgr +#define JRNL_WMGR_MAXWAITUS 100 ///< Max. wait time (us) before submitting AIO + +#define JRNL_INFO_EXTENSION "jinf" ///< Extension for journal info files +#define JRNL_DATA_EXTENSION "jdat" ///< Extension for journal data files +#define RHM_JDAT_TXA_MAGIC 0x614d4852 ///< ("RHMa" in little endian) Magic for dtx abort hdrs +#define RHM_JDAT_TXC_MAGIC 0x634d4852 ///< ("RHMc" in little endian) Magic for dtx commit hdrs +#define RHM_JDAT_DEQ_MAGIC 0x644d4852 ///< ("RHMd" in little endian) Magic for deq rec hdrs +#define RHM_JDAT_ENQ_MAGIC 0x654d4852 ///< ("RHMe" in little endian) Magic for enq rec hdrs +#define RHM_JDAT_FILE_MAGIC 0x664d4852 ///< ("RHMf" in little endian) Magic for file hdrs +#define RHM_JDAT_EMPTY_MAGIC 0x784d4852 ///< ("RHMx" in little endian) Magic for empty dblk +#define RHM_JDAT_VERSION 0x01 ///< Version (of file layout) +#define RHM_CLEAN_CHAR 0xff ///< Char used to clear empty space on disk + +#define RHM_LENDIAN_FLAG 0 ///< Value of little endian flag on disk +#define RHM_BENDIAN_FLAG 1 ///< Value of big endian flag on disk + +#endif // ifndef mrg_journal_jcfg_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jcfg.hpp b/cpp/src/qpid/legacystore/jrnl/jcfg.hpp deleted file mode 100644 index 183223fe7f..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/jcfg.hpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file jcfg.hpp - * - * Qpid asynchronous store plugin library - * - * This file contains \#defines that control the implementation details of - * the journal. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_jcfg_hpp -#define mrg_journal_jcfg_hpp - -#if defined(__i386__) /* little endian, 32 bits */ -#define JRNL_LITTLE_ENDIAN -#define JRNL_32_BIT -#elif defined(__PPC__) || defined(__s390__) /* big endian, 32 bits */ -#define JRNL_BIG_ENDIAN -#define JRNL_32_BIT -#elif defined(__ia64__) || defined(__x86_64__) || defined(__alpha__) /* little endian, 64 bits */ -#define JRNL_LITTLE_ENDIAN -#define JRNL_64_BIT -#elif defined(__powerpc64__) || defined(__s390x__) /* big endian, 64 bits */ -#define JRNL_BIG_ENDIAN -#define JRNL_64_BIT -#else -#error endian? -#endif - - -/** -* Rule: Data block size (JRNL_DBLK_SIZE) MUST be a power of 2 such that -*
-* JRNL_DBLK_SIZE * JRNL_SBLK_SIZE == n * 512 (n = 1,2,3...)
-* 
-* (The disk softblock size is 512 for Linux kernels >= 2.6) -*/ -#define JRNL_DBLK_SIZE 128 ///< Data block size in bytes (CANNOT BE LESS THAN 32!) -#define JRNL_SBLK_SIZE 4 ///< Disk softblock size in multiples of JRNL_DBLK_SIZE -#define JRNL_MIN_FILE_SIZE 128 ///< Min. jrnl file size in sblks (excl. file_hdr) -#define JRNL_MAX_FILE_SIZE 4194176 ///< Max. jrnl file size in sblks (excl. file_hdr) -#define JRNL_MIN_NUM_FILES 4 ///< Min. number of journal files -#define JRNL_MAX_NUM_FILES 64 ///< Max. number of journal files -#define JRNL_ENQ_THRESHOLD 80 ///< Percent full when enqueue connection will be closed - -#define JRNL_RMGR_PAGE_SIZE 128 ///< Journal page size in softblocks -#define JRNL_RMGR_PAGES 16 ///< Number of pages to use in wmgr - -#define JRNL_WMGR_DEF_PAGE_SIZE 64 ///< Journal write page size in softblocks (default) -#define JRNL_WMGR_DEF_PAGES 32 ///< Number of pages to use in wmgr (default) - -#define JRNL_WMGR_MAXDTOKPP 1024 ///< Max. dtoks (data blocks) per page in wmgr -#define JRNL_WMGR_MAXWAITUS 100 ///< Max. wait time (us) before submitting AIO - -#define JRNL_INFO_EXTENSION "jinf" ///< Extension for journal info files -#define JRNL_DATA_EXTENSION "jdat" ///< Extension for journal data files -#define RHM_JDAT_TXA_MAGIC 0x614d4852 ///< ("RHMa" in little endian) Magic for dtx abort hdrs -#define RHM_JDAT_TXC_MAGIC 0x634d4852 ///< ("RHMc" in little endian) Magic for dtx commit hdrs -#define RHM_JDAT_DEQ_MAGIC 0x644d4852 ///< ("RHMd" in little endian) Magic for deq rec hdrs -#define RHM_JDAT_ENQ_MAGIC 0x654d4852 ///< ("RHMe" in little endian) Magic for enq rec hdrs -#define RHM_JDAT_FILE_MAGIC 0x664d4852 ///< ("RHMf" in little endian) Magic for file hdrs -#define RHM_JDAT_EMPTY_MAGIC 0x784d4852 ///< ("RHMx" in little endian) Magic for empty dblk -#define RHM_JDAT_VERSION 0x01 ///< Version (of file layout) -#define RHM_CLEAN_CHAR 0xff ///< Char used to clear empty space on disk - -#define RHM_LENDIAN_FLAG 0 ///< Value of little endian flag on disk -#define RHM_BENDIAN_FLAG 1 ///< Value of big endian flag on disk - -#endif // ifndef mrg_journal_jcfg_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jcntl.h b/cpp/src/qpid/legacystore/jrnl/jcntl.h new file mode 100644 index 0000000000..b7d4cc7ca7 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/jcntl.h @@ -0,0 +1,722 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file jcntl.hpp + * + * Qpid asynchronous store plugin library + * + * Messaging journal top-level control and interface class + * mrg::journal::jcntl. See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_jcntl_hpp +#define mrg_journal_jcntl_hpp + +namespace mrg +{ +namespace journal +{ + class jcntl; +} +} + +#include +#include +#include "jrnl/jdir.hpp" +#include "jrnl/fcntl.hpp" +#include "jrnl/lpmgr.hpp" +#include "jrnl/rcvdat.hpp" +#include "jrnl/slock.hpp" +#include "jrnl/smutex.hpp" +#include "jrnl/rmgr.hpp" +#include "jrnl/wmgr.hpp" +#include "jrnl/wrfc.hpp" + +namespace mrg +{ +namespace journal +{ + + /** + * \brief Access and control interface for the journal. This is the top-level class for the + * journal. + * + * This is the top-level journal class; one instance of this class controls one instance of the + * journal and all its files and associated control structures. Besides this class, the only + * other class that needs to be used at a higher level is the data_tok class, one instance of + * which is used per data block written to the journal, and is used to track its status through + * the AIO enqueue, read and dequeue process. + */ + class jcntl + { + protected: + /** + * \brief Journal ID + * + * This string uniquely identifies this journal instance. It will most likely be associated + * with the identity of the message queue with which it is associated. + */ + // TODO: This is not included in any files at present, add to file_hdr? + std::string _jid; + + /** + * \brief Journal directory + * + * This string stores the path to the journal directory. It may be absolute or relative, and + * should not end in a file separator character. (e.g. "/fastdisk/jdata" is correct, + * "/fastdisk/jdata/" is not.) + */ + jdir _jdir; + + /** + * \brief Base filename + * + * This string contains the base filename used for the journal files. The filenames will + * start with this base, and have various sections added to it to derive the final file names + * that will be written to disk. No file separator characters should be included here, but + * all other legal filename characters are valid. + */ + std::string _base_filename; + + /** + * \brief Initialized flag + * + * This flag starts out set to false, is set to true once this object has been initialized, + * either by calling initialize() or recover(). + */ + bool _init_flag; + + /** + * \brief Stopped flag + * + * This flag starts out false, and is set to true when stop() is called. At this point, the + * journal will no longer accept messages until either initialize() or recover() is called. + * There is no way other than through initialization to reset this flag. + */ + // TODO: It would be helpful to distinguish between states stopping and stopped. If stop(true) is called, + // then we are stopping, but must wait for all outstanding aios to return before being finally stopped. During + // this period, however, no new enqueue/dequeue/read requests may be accepted. + bool _stop_flag; + + /** + * \brief Read-only state flag used during recover. + * + * When true, this flag prevents journal write operations (enqueue and dequeue), but + * allows read to occur. It is used during recovery, and is reset when recovered() is + * called. + */ + bool _readonly_flag; + + /** + * \brief If set, calls stop() if the jouranl write pointer overruns dequeue low water + * marker. If not set, then attempts to write will throw exceptions until the journal + * file low water marker moves to the next journal file. + */ + bool _autostop; ///< Autostop flag - stops journal when overrun occurs + + // Journal control structures + u_int32_t _jfsize_sblks; ///< Journal file size in sblks + lpmgr _lpmgr; ///< LFID-PFID manager tracks inserted journal files + enq_map _emap; ///< Enqueue map for low water mark management + txn_map _tmap; ///< Transaction map open transactions + rrfc _rrfc; ///< Read journal rotating file controller + wrfc _wrfc; ///< Write journal rotating file controller + rmgr _rmgr; ///< Read page manager which manages AIO + wmgr _wmgr; ///< Write page manager which manages AIO + rcvdat _rcvdat; ///< Recovery data used for recovery + smutex _wr_mutex; ///< Mutex for journal writes + + public: + static timespec _aio_cmpl_timeout; ///< Timeout for blocking libaio returns + static timespec _final_aio_cmpl_timeout; ///< Timeout for blocking libaio returns when stopping or finalizing + + /** + * \brief Journal constructor. + * + * Constructor which sets the physical file location and base name. + * + * \param jid A unique identifier for this journal instance. + * \param jdir The directory which will contain the journal files. + * \param base_filename The string which will be used to start all journal filenames. + */ + jcntl(const std::string& jid, const std::string& jdir, const std::string& base_filename); + + /** + * \brief Destructor. + */ + virtual ~jcntl(); + + inline const std::string& id() const { return _jid; } + inline const std::string& jrnl_dir() const { return _jdir.dirname(); } + + /** + * \brief Initialize the journal for storing data. + * + * Initialize the journal by creating new journal data files and initializing internal + * control structures. When complete, the journal will be empty, and ready to store data. + * + * NOTE: Any existing journal will be ignored by this operation. To use recover + * the data from an existing journal, use recover(). + * + * NOTE: If NULL is passed to the deque pointers, they will be internally created + * and deleted. + * + * NOTE: If NULL is passed to the callbacks, internal default callbacks will be + * used. + * + * \param num_jfiles The number of journal files to be created. + * \param auto_expand If true, allows journal file auto-expansion. In this mode, the journal will automatically + * add files to the journal if it runs out of space. No more than ae_max_jfiles may be added. If false, then + * no files are added and an exception will be thrown if the journal runs out of file space. + * \param ae_max_jfiles Upper limit of journal files for auto-expand mode. When auto_expand is true, this is the + * maximum total number of files allowed in the journal (original plus those added by auto-expand mode). If + * this number of files exist and the journal runs out of space, an exception will be thrown. This number + * must be greater than the num_jfiles parameter value but cannot exceed the maximum number of files for a + * single journal; if num_jfiles is already at its maximum value, then auto-expand will be disabled. + * \param jfsize_sblks The size of each journal file expressed in softblocks. + * \param wcache_num_pages The number of write cache pages to create. + * \param wcache_pgsize_sblks The size in sblks of each write cache page. + * \param cbp Pointer to object containing callback functions for read and write operations. May be 0 (NULL). + * + * \exception TODO + */ + void initialize(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles, + const u_int32_t jfsize_sblks, const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks, + aio_callback* const cbp); + + /** + * /brief Initialize journal by recovering state from previously written journal. + * + * Initialize journal by recovering state from previously written journal. The journal files + * are analyzed, and all records that have not been dequeued and that remain in the journal + * will be available for reading. The journal is placed in a read-only state until + * recovered() is called; any calls to enqueue or dequeue will fail with an exception + * in this state. + * + * NOTE: If NULL is passed to the deque pointers, they will be internally created + * and deleted. + * + * NOTE: If NULL is passed to the callbacks, internal default callbacks will be + * used. + * + * \param num_jfiles The number of journal files to be created. + * \param auto_expand If true, allows journal file auto-expansion. In this mode, the journal will automatically + * add files to the journal if it runs out of space. No more than ae_max_jfiles may be added. If false, then + * no files are added and an exception will be thrown if the journal runs out of file space. + * \param ae_max_jfiles Upper limit of journal files for auto-expand mode. When auto_expand is true, this is the + * maximum total number of files allowed in the journal (original plus those added by auto-expand mode). If + * this number of files exist and the journal runs out of space, an exception will be thrown. This number + * must be greater than the num_jfiles parameter value but cannot exceed the maximum number of files for a + * single journal; if num_jfiles is already at its maximum value, then auto-expand will be disabled. + * \param jfsize_sblks The size of each journal file expressed in softblocks. + * \param wcache_num_pages The number of write cache pages to create. + * \param wcache_pgsize_sblks The size in sblks of each write cache page. + * \param cbp Pointer to object containing callback functions for read and write operations. May be 0 (NULL). + * \param prep_txn_list_ptr + * \param highest_rid Returns the highest rid found in the journal during recover + * + * \exception TODO + */ + void recover(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles, + const u_int32_t jfsize_sblks, const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks, + aio_callback* const cbp, const std::vector* prep_txn_list_ptr, u_int64_t& highest_rid); + + /** + * \brief Notification to the journal that recovery is complete and that normal operation + * may resume. + * + * This call notifies the journal that recovery is complete and that normal operation + * may resume. The read pointers are reset so that all records read as a part of recover + * may be re-read during normal operation. The read-only flag is then reset, allowing + * enqueue and dequeue operations to resume. + * + * \exception TODO + */ + void recover_complete(); + + /** + * \brief Stops journal and deletes all journal files. + * + * Clear the journal directory of all journal files matching the base filename. + * + * \exception TODO + */ + void delete_jrnl_files(); + + /** + * \brief Enqueue data. + * + * Enqueue data or part thereof. If a large data block is being written, then it may be + * enqueued in parts by setting this_data_len to the size of the data being written in this + * call. The total data size must be known in advance, however, as this is written into the + * record header on the first record write. The state of the write (i.e. how much has been + * written so far) is maintained in the data token dtokp. Partial writes will return in state + * ENQ_PART. + * + * Note that a return value of anything other than RHM_IORES_SUCCESS implies that this write + * operation did not complete successfully or was partially completed. The action taken under + * these conditions depends on the value of the return. For example, RHM_IORES_AIO_WAIT + * implies that all pages in the write page cache are waiting for AIO operations to return, + * and that the call should be remade after waiting a bit. + * + * Example: If a write of 99 kB is divided into three equal parts, then the following states + * and returns would characterize a successful operation: + *
+        *                            dtok.    dtok.   dtok.
+        * Pperation         Return   wstate() dsize() written() Comment
+        * -----------------+--------+--------+-------+---------+------------------------------------
+        *                            NONE     0       0         Value of dtok before op
+        * edr(99000, 33000) SUCCESS  ENQ_PART 99000   33000     Enqueue part 1
+        * edr(99000, 33000) AIO_WAIT ENQ_PART 99000   50000     Enqueue part 2, not completed
+        * edr(99000, 33000) SUCCESS  ENQ_PART 99000   66000     Enqueue part 2 again
+        * edr(99000, 33000) SUCCESS  ENQ      99000   99000     Enqueue part 3
+        * 
+ * + * \param data_buff Pointer to data to be enqueued for this enqueue operation. + * \param tot_data_len Total data length. + * \param this_data_len Amount to be written in this enqueue operation. + * \param dtokp Pointer to data token which contains the details of the enqueue operation. + * \param transient Flag indicating transient persistence (ie, ignored on recover). + * + * \exception TODO + */ + iores enqueue_data_record(const void* const data_buff, const std::size_t tot_data_len, + const std::size_t this_data_len, data_tok* dtokp, const bool transient = false); + + iores enqueue_extern_data_record(const std::size_t tot_data_len, data_tok* dtokp, + const bool transient = false); + + /** + * \brief Enqueue data. + * + * \param data_buff Pointer to data to be enqueued for this enqueue operation. + * \param tot_data_len Total data length. + * \param this_data_len Amount to be written in this enqueue operation. + * \param dtokp Pointer to data token which contains the details of the enqueue operation. + * \param xid String containing xid. An empty string (i.e. length=0) will be considered + * non-transactional. + * \param transient Flag indicating transient persistence (ie, ignored on recover). + * + * \exception TODO + */ + iores enqueue_txn_data_record(const void* const data_buff, const std::size_t tot_data_len, + const std::size_t this_data_len, data_tok* dtokp, const std::string& xid, + const bool transient = false); + iores enqueue_extern_txn_data_record(const std::size_t tot_data_len, data_tok* dtokp, + const std::string& xid, const bool transient = false); + + /* TODO + ** + * \brief Retrieve details of next record to be read without consuming the record. + * + * Retrieve information about current read record. A pointer to the data is returned, along + * with the data size and available data size. Data is considered "available" when the AIO + * operations to fill page-cache pages from disk have returned, and is ready for consumption. + * + * If dsize_avail < dsize, then not all of the data is available or part of + * the data is in non-contiguous memory, and a subsequent call will update both the pointer + * and dsize_avail if more pages have returned from AIO. + * + * The dsize_avail parameter will return the amount of data from this record that is + * available in the page cache as contiguous memory, even if it spans page cache boundaries. + * However, if a record spans the end of the page cache and continues at the beginning, even + * if both parts are ready for consumption, then this must be divided into at least two + * get_data_record() operations, as the data is contained in at least two non-contiguous + * segments of the page cache. + * + * Once all the available data for a record is exposed, it can not be read again using + * this function. It must be consumed prior to getting the next record. This can be done by + * calling discard_data_record() or read_data_record(). However, if parameter + * auto_discard is set to true, then this record will be automatically + * consumed when the entire record has become available without having to explicitly call + * discard_next_data_record() or read_data_record(). + * + * If the current record is an open transactional record, then it cannot be read until it is + * committed. If it is aborted, it can never be read. Under this condition, get_data_record() + * will return RHM_IORES_TXPENDING, the data pointer will be set to NULL and all data + * lengths will be set to 0. + * + * Example: Read a record of 30k. Assume a read page cache of 10 pages of size 10k starting + * at address base_ptr (page0 = base_ptr, page1 = page_ptr+10k, etc.). The first 15k of + * the record falls at the end of the page cache, the remaining 15k folded to the beginning. + * The current page (page 8) containing 5k is available, the remaining pages which contain + * this record are pending AIO return: + *
+        * call       dsize
+        * no.  dsize avail data ptr     Return   Comment
+        * ----+-----+-----+------------+--------+--------------------------------------------------
+        * 1    30k   5k    base_ptr+85k SUCCESS  Initial call, read first 5k
+        * 2    30k   0k    base_ptr+90k AIO_WAIT AIO still pending; no further pages avail
+        * 3    30k   10k   base_ptr+90k SUCCESS  AIO now returned; now read till end of page cache
+        * 4    30k   15k   base_ptr     SUCCESS  data_ptr now pointing to start of page cache
+        * 
+ * + * \param rid Reference that returns the record ID (rid) + * \param dsize Reference that returns the total data size of the record data . + * \param dsize_avail Reference that returns the amount of the data that is available for + * consumption. + * \param data Pointer to data pointer which will point to the first byte of the next record + * data. + * \param auto_discard If true, automatically discard the record being read if + * the entire record is available (i.e. dsize == dsize_avail). Otherwise + * discard_next_data_record() must be explicitly called. + * + * \exception TODO + * + // *** NOT YET IMPLEMENTED *** + iores get_data_record(const u_int64_t& rid, const std::size_t& dsize, + const std::size_t& dsize_avail, const void** const data, bool auto_discard = false); + */ + + /* TODO + ** + * \brief Discard (skip) next record to be read without reading or retrieving it. + * + * \exception TODO + * + // *** NOT YET IMPLEMENTED *** + iores discard_data_record(data_tok* const dtokp); + */ + + /** + * \brief Reads data from the journal. It is the responsibility of the reader to free + * the memory that is allocated through this call - see below for details. + * + * Reads the next non-dequeued data record from the journal. + * + * Note that this call allocates memory into which the data and XID are copied. It + * is the responsibility of the caller to free this memory. The memory for the data and + * XID are allocated in a single call, and the XID precedes the data in the memory space. + * Thus, where an XID exists, freeing the XID pointer will free both the XID and data memory. + * However, if an XID does not exist for the message, the XID pointer xidpp is set to NULL, + * and it is the data pointer datapp that must be freed. Should neither an XID nor data be + * present (ie an empty record), then no memory is allocated, and both pointers will be NULL. + * In this case, there is no need to free memory. + * + * TODO: Fix this lousy interface. The caller should NOT be required to clean up these + * pointers! Rather use a struct, or better still, let the data token carry the data and + * xid pointers and lengths, and have the data token both allocate and delete. + * + * \param datapp Pointer to pointer that will be set to point to memory allocated and + * containing the data. Will be set to NULL if the call fails or there is no data + * in the record. + * \param dsize Ref that will be set to the size of the data. Will be set to 0 if the call + * fails or if there is no data in the record. + * \param xidpp Pointer to pointer that will be set to point to memory allocated and + * containing the XID. Will be set to NULL if the call fails or there is no XID attached + * to this record. + * \param xidsize Ref that will be set to the size of the XID. + * \param transient Ref that will be set true if record is transient. + * \param external Ref that will be set true if record is external. In this case, the data + * pointer datapp will be set to NULL, but dsize will contain the size of the data. + * NOTE: If there is an xid, then xidpp must be freed. + * \param dtokp Pointer to data_tok instance for this data, used to track state of data + * through journal. + * \param ignore_pending_txns When false (default), if the next record to be read is locked + * by a pending transaction, the read fails with RHM_IORES_TXPENDING. However, if set + * to true, then locks are ignored. This is required for reading of the Transaction + * Prepared List (TPL) which may have its entries locked, but may be read from + * time-to-time, and needs all its records (locked and unlocked) to be available. + * + * \exception TODO + */ + iores read_data_record(void** const datapp, std::size_t& dsize, void** const xidpp, + std::size_t& xidsize, bool& transient, bool& external, data_tok* const dtokp, + bool ignore_pending_txns = false); + + /** + * \brief Dequeues (marks as no longer needed) data record in journal. + * + * Dequeues (marks as no longer needed) data record in journal. Note that it is possible + * to use the same data token instance used to enqueue this data; it contains the record ID + * needed to correctly mark this data as dequeued in the journal. Otherwise the RID of the + * record to be dequeued and the write state of ENQ must be manually set in a new or reset + * instance of data_tok. + * + * \param dtokp Pointer to data_tok instance for this data, used to track state of data + * through journal. + * \param txn_coml_commit Only used for preparedXID journal. When used for dequeueing + * prepared XID list items, sets whether the complete() was called in commit or abort + * mode. + * + * \exception TODO + */ + iores dequeue_data_record(data_tok* const dtokp, const bool txn_coml_commit = false); + + /** + * \brief Dequeues (marks as no longer needed) data record in journal. + * + * Dequeues (marks as no longer needed) data record in journal as part of a transaction. + * Note that it is possible to use the same data token instance used to enqueue this data; + * it contains the RID needed to correctly mark this data as dequeued in the journal. + * Otherwise the RID of the record to be dequeued and the write state of ENQ must be + * manually set in a new or reset instance of data_tok. + * + * \param dtokp Pointer to data_tok instance for this data, used to track state of data + * through journal. + * \param xid String containing xid. An empty string (i.e. length=0) will be considered + * non-transactional. + * \param txn_coml_commit Only used for preparedXID journal. When used for dequeueing + * prepared XID list items, sets whether the complete() was called in commit or abort + * mode. + * + * \exception TODO + */ + iores dequeue_txn_data_record(data_tok* const dtokp, const std::string& xid, const bool txn_coml_commit = false); + + /** + * \brief Abort the transaction for all records enqueued or dequeued with the matching xid. + * + * Abort the transaction for all records enqueued with the matching xid. All enqueued records + * are effectively deleted from the journal, and can not be read. All dequeued records remain + * as though they had never been dequeued. + * + * \param dtokp Pointer to data_tok instance for this data, used to track state of data + * through journal. + * \param xid String containing xid. + * + * \exception TODO + */ + iores txn_abort(data_tok* const dtokp, const std::string& xid); + + /** + * \brief Commit the transaction for all records enqueued or dequeued with the matching xid. + * + * Commit the transaction for all records enqueued with the matching xid. All enqueued + * records are effectively released for reading and dequeueing. All dequeued records are + * removed and can no longer be accessed. + * + * \param dtokp Pointer to data_tok instance for this data, used to track state of data + * through journal. + * \param xid String containing xid. + * + * \exception TODO + */ + iores txn_commit(data_tok* const dtokp, const std::string& xid); + + /** + * \brief Check whether all the enqueue records for the given xid have reached disk. + * + * \param xid String containing xid. + * + * \exception TODO + */ + bool is_txn_synced(const std::string& xid); + + /** + * \brief Forces a check for returned AIO write events. + * + * Forces a check for returned AIO write events. This is normally performed by enqueue() and + * dequeue() operations, but if these operations cease, then this call needs to be made to + * force the processing of any outstanding AIO operations. + */ + int32_t get_wr_events(timespec* const timeout); + + /** + * \brief Forces a check for returned AIO read events. + * + * Forces a check for returned AIO read events. This is normally performed by read_data() + * operations, but if these operations cease, then this call needs to be made to force the + * processing of any outstanding AIO operations. + */ + int32_t get_rd_events(timespec* const timeout); + + /** + * \brief Stop the journal from accepting any further requests to read or write data. + * + * This operation is used to stop the journal. This is the normal mechanism for bringing the + * journal to an orderly stop. Any outstanding AIO operations or partially written pages in + * the write page cache will by flushed and will complete. + * + * Note: The journal cannot be restarted without either initializing it or restoring + * it. + * + * \param block_till_aio_cmpl If true, will block the thread while waiting for all + * outstanding AIO operations to complete. + */ + void stop(const bool block_till_aio_cmpl = false); + + /** + * \brief Force a flush of the write page cache, creating a single AIO write operation. + */ + iores flush(const bool block_till_aio_cmpl = false); + + inline u_int32_t get_enq_cnt() const { return _emap.size(); } + + inline u_int32_t get_wr_aio_evt_rem() const { slock l(_wr_mutex); return _wmgr.get_aio_evt_rem(); } + + inline u_int32_t get_rd_aio_evt_rem() const { return _rmgr.get_aio_evt_rem(); } + + inline u_int32_t get_wr_outstanding_aio_dblks() const + { return _wrfc.aio_outstanding_dblks(); } + + inline u_int32_t get_wr_outstanding_aio_dblks(u_int16_t lfid) const + { return _lpmgr.get_fcntlp(lfid)->wr_aio_outstanding_dblks(); } + + inline u_int32_t get_rd_outstanding_aio_dblks() const + { return _rrfc.aio_outstanding_dblks(); } + + inline u_int32_t get_rd_outstanding_aio_dblks(u_int16_t lfid) const + { return _lpmgr.get_fcntlp(lfid)->rd_aio_outstanding_dblks(); } + + inline u_int16_t get_rd_fid() const { return _rrfc.index(); } + inline u_int16_t get_wr_fid() const { return _wrfc.index(); } + u_int16_t get_earliest_fid(); + + /** + * \brief Check if a particular rid is enqueued. Note that this function will return + * false if the rid is transactionally enqueued and is not committed, or if it is + * locked (i.e. transactionally dequeued, but the dequeue has not been committed). + */ + inline bool is_enqueued(const u_int64_t rid, bool ignore_lock = false) + { return _emap.is_enqueued(rid, ignore_lock); } + inline bool is_locked(const u_int64_t rid) + { if (_emap.is_enqueued(rid, true) < enq_map::EMAP_OK) return false; return _emap.is_locked(rid) == enq_map::EMAP_TRUE; } + inline void enq_rid_list(std::vector& rids) { _emap.rid_list(rids); } + inline void enq_xid_list(std::vector& xids) { _tmap.xid_list(xids); } + inline u_int32_t get_open_txn_cnt() const { return _tmap.size(); } + // TODO Make this a const, but txn_map must support const first. + inline txn_map& get_txn_map() { return _tmap; } + + /** + * \brief Check if the journal is stopped. + * + * \return true if the jouranl is stopped; + * false otherwise. + */ + inline bool is_stopped() { return _stop_flag; } + + /** + * \brief Check if the journal is ready to read and write data. + * + * Checks if the journal is ready to read and write data. This function will return + * true if the journal has been either initialized or restored, and the stop() + * function has not been called since the initialization. + * + * Note that the journal may also be stopped if an internal error occurs (such as running out + * of data journal file space). + * + * \return true if the journal is ready to read and write data; + * false otherwise. + */ + inline bool is_ready() const { return _init_flag && !_stop_flag; } + + inline bool is_read_only() const { return _readonly_flag; } + + /** + * \brief Get the journal directory. + * + * This returns the journal directory as set during initialization. This is the directory + * into which the journal files will be written. + */ + inline const std::string& dirname() const { return _jdir.dirname(); } + + /** + * \brief Get the journal base filename. + * + * Get the journal base filename as set during initialization. This is the prefix used in all + * journal files of this instance. Note that if more than one instance of the journal shares + * the same directory, their base filenames MUST be different or else the instances + * will overwrite one another. + */ + inline const std::string& base_filename() const { return _base_filename; } + + inline u_int16_t num_jfiles() const { return _lpmgr.num_jfiles(); } + + inline fcntl* get_fcntlp(const u_int16_t lfid) const { return _lpmgr.get_fcntlp(lfid); } + + inline u_int32_t jfsize_sblks() const { return _jfsize_sblks; } + + // Logging + virtual void log(log_level level, const std::string& log_stmt) const; + virtual void log(log_level level, const char* const log_stmt) const; + + // FIXME these are _rmgr to _wmgr interactions, remove when _rmgr contains ref to _wmgr: + void chk_wr_frot(); + inline u_int32_t unflushed_dblks() { return _wmgr.unflushed_dblks(); } + void fhdr_wr_sync(const u_int16_t lid); + inline u_int32_t wr_subm_cnt_dblks(const u_int16_t lfid) const { return _lpmgr.get_fcntlp(lfid)->wr_subm_cnt_dblks(); } + + // Management instrumentation callbacks + inline virtual void instr_incr_outstanding_aio_cnt() {} + inline virtual void instr_decr_outstanding_aio_cnt() {} + + /** + * /brief Static function for creating new fcntl objects for use with obj_arr. + */ + static fcntl* new_fcntl(jcntl* const jcp, const u_int16_t lid, const u_int16_t fid, const rcvdat* const rdp); + + protected: + static bool _init; + static bool init_statics(); + + /** + * \brief Check status of journal before allowing write operations. + */ + void check_wstatus(const char* fn_name) const; + + /** + * \brief Check status of journal before allowing read operations. + */ + void check_rstatus(const char* fn_name) const; + + /** + * \brief Write info file <basefilename>.jinf to disk + */ + void write_infofile() const; + + /** + * \brief Call that blocks while waiting for all outstanding AIOs to complete + */ + void aio_cmpl_wait(); + + /** + * \brief Call that blocks until at least one message returns; used to wait for + * AIO wait conditions to clear. + */ + bool handle_aio_wait(const iores res, iores& resout, const data_tok* dtp); + + /** + * \brief Analyze journal for recovery. + */ + void rcvr_janalyze(rcvdat& rd, const std::vector* prep_txn_list_ptr); + + bool rcvr_get_next_record(u_int16_t& fid, std::ifstream* ifsp, bool& lowi, rcvdat& rd); + + bool decode(jrec& rec, u_int16_t& fid, std::ifstream* ifsp, std::size_t& cum_size_read, + rec_hdr& h, bool& lowi, rcvdat& rd, std::streampos& rec_offset); + + bool jfile_cycle(u_int16_t& fid, std::ifstream* ifsp, bool& lowi, rcvdat& rd, + const bool jump_fro); + + bool check_owi(const u_int16_t fid, rec_hdr& h, bool& lowi, rcvdat& rd, + std::streampos& read_pos); + + void check_journal_alignment(const u_int16_t fid, std::streampos& rec_offset, rcvdat& rd); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_jcntl_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jcntl.hpp b/cpp/src/qpid/legacystore/jrnl/jcntl.hpp deleted file mode 100644 index b7d4cc7ca7..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/jcntl.hpp +++ /dev/null @@ -1,722 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file jcntl.hpp - * - * Qpid asynchronous store plugin library - * - * Messaging journal top-level control and interface class - * mrg::journal::jcntl. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_jcntl_hpp -#define mrg_journal_jcntl_hpp - -namespace mrg -{ -namespace journal -{ - class jcntl; -} -} - -#include -#include -#include "jrnl/jdir.hpp" -#include "jrnl/fcntl.hpp" -#include "jrnl/lpmgr.hpp" -#include "jrnl/rcvdat.hpp" -#include "jrnl/slock.hpp" -#include "jrnl/smutex.hpp" -#include "jrnl/rmgr.hpp" -#include "jrnl/wmgr.hpp" -#include "jrnl/wrfc.hpp" - -namespace mrg -{ -namespace journal -{ - - /** - * \brief Access and control interface for the journal. This is the top-level class for the - * journal. - * - * This is the top-level journal class; one instance of this class controls one instance of the - * journal and all its files and associated control structures. Besides this class, the only - * other class that needs to be used at a higher level is the data_tok class, one instance of - * which is used per data block written to the journal, and is used to track its status through - * the AIO enqueue, read and dequeue process. - */ - class jcntl - { - protected: - /** - * \brief Journal ID - * - * This string uniquely identifies this journal instance. It will most likely be associated - * with the identity of the message queue with which it is associated. - */ - // TODO: This is not included in any files at present, add to file_hdr? - std::string _jid; - - /** - * \brief Journal directory - * - * This string stores the path to the journal directory. It may be absolute or relative, and - * should not end in a file separator character. (e.g. "/fastdisk/jdata" is correct, - * "/fastdisk/jdata/" is not.) - */ - jdir _jdir; - - /** - * \brief Base filename - * - * This string contains the base filename used for the journal files. The filenames will - * start with this base, and have various sections added to it to derive the final file names - * that will be written to disk. No file separator characters should be included here, but - * all other legal filename characters are valid. - */ - std::string _base_filename; - - /** - * \brief Initialized flag - * - * This flag starts out set to false, is set to true once this object has been initialized, - * either by calling initialize() or recover(). - */ - bool _init_flag; - - /** - * \brief Stopped flag - * - * This flag starts out false, and is set to true when stop() is called. At this point, the - * journal will no longer accept messages until either initialize() or recover() is called. - * There is no way other than through initialization to reset this flag. - */ - // TODO: It would be helpful to distinguish between states stopping and stopped. If stop(true) is called, - // then we are stopping, but must wait for all outstanding aios to return before being finally stopped. During - // this period, however, no new enqueue/dequeue/read requests may be accepted. - bool _stop_flag; - - /** - * \brief Read-only state flag used during recover. - * - * When true, this flag prevents journal write operations (enqueue and dequeue), but - * allows read to occur. It is used during recovery, and is reset when recovered() is - * called. - */ - bool _readonly_flag; - - /** - * \brief If set, calls stop() if the jouranl write pointer overruns dequeue low water - * marker. If not set, then attempts to write will throw exceptions until the journal - * file low water marker moves to the next journal file. - */ - bool _autostop; ///< Autostop flag - stops journal when overrun occurs - - // Journal control structures - u_int32_t _jfsize_sblks; ///< Journal file size in sblks - lpmgr _lpmgr; ///< LFID-PFID manager tracks inserted journal files - enq_map _emap; ///< Enqueue map for low water mark management - txn_map _tmap; ///< Transaction map open transactions - rrfc _rrfc; ///< Read journal rotating file controller - wrfc _wrfc; ///< Write journal rotating file controller - rmgr _rmgr; ///< Read page manager which manages AIO - wmgr _wmgr; ///< Write page manager which manages AIO - rcvdat _rcvdat; ///< Recovery data used for recovery - smutex _wr_mutex; ///< Mutex for journal writes - - public: - static timespec _aio_cmpl_timeout; ///< Timeout for blocking libaio returns - static timespec _final_aio_cmpl_timeout; ///< Timeout for blocking libaio returns when stopping or finalizing - - /** - * \brief Journal constructor. - * - * Constructor which sets the physical file location and base name. - * - * \param jid A unique identifier for this journal instance. - * \param jdir The directory which will contain the journal files. - * \param base_filename The string which will be used to start all journal filenames. - */ - jcntl(const std::string& jid, const std::string& jdir, const std::string& base_filename); - - /** - * \brief Destructor. - */ - virtual ~jcntl(); - - inline const std::string& id() const { return _jid; } - inline const std::string& jrnl_dir() const { return _jdir.dirname(); } - - /** - * \brief Initialize the journal for storing data. - * - * Initialize the journal by creating new journal data files and initializing internal - * control structures. When complete, the journal will be empty, and ready to store data. - * - * NOTE: Any existing journal will be ignored by this operation. To use recover - * the data from an existing journal, use recover(). - * - * NOTE: If NULL is passed to the deque pointers, they will be internally created - * and deleted. - * - * NOTE: If NULL is passed to the callbacks, internal default callbacks will be - * used. - * - * \param num_jfiles The number of journal files to be created. - * \param auto_expand If true, allows journal file auto-expansion. In this mode, the journal will automatically - * add files to the journal if it runs out of space. No more than ae_max_jfiles may be added. If false, then - * no files are added and an exception will be thrown if the journal runs out of file space. - * \param ae_max_jfiles Upper limit of journal files for auto-expand mode. When auto_expand is true, this is the - * maximum total number of files allowed in the journal (original plus those added by auto-expand mode). If - * this number of files exist and the journal runs out of space, an exception will be thrown. This number - * must be greater than the num_jfiles parameter value but cannot exceed the maximum number of files for a - * single journal; if num_jfiles is already at its maximum value, then auto-expand will be disabled. - * \param jfsize_sblks The size of each journal file expressed in softblocks. - * \param wcache_num_pages The number of write cache pages to create. - * \param wcache_pgsize_sblks The size in sblks of each write cache page. - * \param cbp Pointer to object containing callback functions for read and write operations. May be 0 (NULL). - * - * \exception TODO - */ - void initialize(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks, - aio_callback* const cbp); - - /** - * /brief Initialize journal by recovering state from previously written journal. - * - * Initialize journal by recovering state from previously written journal. The journal files - * are analyzed, and all records that have not been dequeued and that remain in the journal - * will be available for reading. The journal is placed in a read-only state until - * recovered() is called; any calls to enqueue or dequeue will fail with an exception - * in this state. - * - * NOTE: If NULL is passed to the deque pointers, they will be internally created - * and deleted. - * - * NOTE: If NULL is passed to the callbacks, internal default callbacks will be - * used. - * - * \param num_jfiles The number of journal files to be created. - * \param auto_expand If true, allows journal file auto-expansion. In this mode, the journal will automatically - * add files to the journal if it runs out of space. No more than ae_max_jfiles may be added. If false, then - * no files are added and an exception will be thrown if the journal runs out of file space. - * \param ae_max_jfiles Upper limit of journal files for auto-expand mode. When auto_expand is true, this is the - * maximum total number of files allowed in the journal (original plus those added by auto-expand mode). If - * this number of files exist and the journal runs out of space, an exception will be thrown. This number - * must be greater than the num_jfiles parameter value but cannot exceed the maximum number of files for a - * single journal; if num_jfiles is already at its maximum value, then auto-expand will be disabled. - * \param jfsize_sblks The size of each journal file expressed in softblocks. - * \param wcache_num_pages The number of write cache pages to create. - * \param wcache_pgsize_sblks The size in sblks of each write cache page. - * \param cbp Pointer to object containing callback functions for read and write operations. May be 0 (NULL). - * \param prep_txn_list_ptr - * \param highest_rid Returns the highest rid found in the journal during recover - * - * \exception TODO - */ - void recover(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks, - aio_callback* const cbp, const std::vector* prep_txn_list_ptr, u_int64_t& highest_rid); - - /** - * \brief Notification to the journal that recovery is complete and that normal operation - * may resume. - * - * This call notifies the journal that recovery is complete and that normal operation - * may resume. The read pointers are reset so that all records read as a part of recover - * may be re-read during normal operation. The read-only flag is then reset, allowing - * enqueue and dequeue operations to resume. - * - * \exception TODO - */ - void recover_complete(); - - /** - * \brief Stops journal and deletes all journal files. - * - * Clear the journal directory of all journal files matching the base filename. - * - * \exception TODO - */ - void delete_jrnl_files(); - - /** - * \brief Enqueue data. - * - * Enqueue data or part thereof. If a large data block is being written, then it may be - * enqueued in parts by setting this_data_len to the size of the data being written in this - * call. The total data size must be known in advance, however, as this is written into the - * record header on the first record write. The state of the write (i.e. how much has been - * written so far) is maintained in the data token dtokp. Partial writes will return in state - * ENQ_PART. - * - * Note that a return value of anything other than RHM_IORES_SUCCESS implies that this write - * operation did not complete successfully or was partially completed. The action taken under - * these conditions depends on the value of the return. For example, RHM_IORES_AIO_WAIT - * implies that all pages in the write page cache are waiting for AIO operations to return, - * and that the call should be remade after waiting a bit. - * - * Example: If a write of 99 kB is divided into three equal parts, then the following states - * and returns would characterize a successful operation: - *
-        *                            dtok.    dtok.   dtok.
-        * Pperation         Return   wstate() dsize() written() Comment
-        * -----------------+--------+--------+-------+---------+------------------------------------
-        *                            NONE     0       0         Value of dtok before op
-        * edr(99000, 33000) SUCCESS  ENQ_PART 99000   33000     Enqueue part 1
-        * edr(99000, 33000) AIO_WAIT ENQ_PART 99000   50000     Enqueue part 2, not completed
-        * edr(99000, 33000) SUCCESS  ENQ_PART 99000   66000     Enqueue part 2 again
-        * edr(99000, 33000) SUCCESS  ENQ      99000   99000     Enqueue part 3
-        * 
- * - * \param data_buff Pointer to data to be enqueued for this enqueue operation. - * \param tot_data_len Total data length. - * \param this_data_len Amount to be written in this enqueue operation. - * \param dtokp Pointer to data token which contains the details of the enqueue operation. - * \param transient Flag indicating transient persistence (ie, ignored on recover). - * - * \exception TODO - */ - iores enqueue_data_record(const void* const data_buff, const std::size_t tot_data_len, - const std::size_t this_data_len, data_tok* dtokp, const bool transient = false); - - iores enqueue_extern_data_record(const std::size_t tot_data_len, data_tok* dtokp, - const bool transient = false); - - /** - * \brief Enqueue data. - * - * \param data_buff Pointer to data to be enqueued for this enqueue operation. - * \param tot_data_len Total data length. - * \param this_data_len Amount to be written in this enqueue operation. - * \param dtokp Pointer to data token which contains the details of the enqueue operation. - * \param xid String containing xid. An empty string (i.e. length=0) will be considered - * non-transactional. - * \param transient Flag indicating transient persistence (ie, ignored on recover). - * - * \exception TODO - */ - iores enqueue_txn_data_record(const void* const data_buff, const std::size_t tot_data_len, - const std::size_t this_data_len, data_tok* dtokp, const std::string& xid, - const bool transient = false); - iores enqueue_extern_txn_data_record(const std::size_t tot_data_len, data_tok* dtokp, - const std::string& xid, const bool transient = false); - - /* TODO - ** - * \brief Retrieve details of next record to be read without consuming the record. - * - * Retrieve information about current read record. A pointer to the data is returned, along - * with the data size and available data size. Data is considered "available" when the AIO - * operations to fill page-cache pages from disk have returned, and is ready for consumption. - * - * If dsize_avail < dsize, then not all of the data is available or part of - * the data is in non-contiguous memory, and a subsequent call will update both the pointer - * and dsize_avail if more pages have returned from AIO. - * - * The dsize_avail parameter will return the amount of data from this record that is - * available in the page cache as contiguous memory, even if it spans page cache boundaries. - * However, if a record spans the end of the page cache and continues at the beginning, even - * if both parts are ready for consumption, then this must be divided into at least two - * get_data_record() operations, as the data is contained in at least two non-contiguous - * segments of the page cache. - * - * Once all the available data for a record is exposed, it can not be read again using - * this function. It must be consumed prior to getting the next record. This can be done by - * calling discard_data_record() or read_data_record(). However, if parameter - * auto_discard is set to true, then this record will be automatically - * consumed when the entire record has become available without having to explicitly call - * discard_next_data_record() or read_data_record(). - * - * If the current record is an open transactional record, then it cannot be read until it is - * committed. If it is aborted, it can never be read. Under this condition, get_data_record() - * will return RHM_IORES_TXPENDING, the data pointer will be set to NULL and all data - * lengths will be set to 0. - * - * Example: Read a record of 30k. Assume a read page cache of 10 pages of size 10k starting - * at address base_ptr (page0 = base_ptr, page1 = page_ptr+10k, etc.). The first 15k of - * the record falls at the end of the page cache, the remaining 15k folded to the beginning. - * The current page (page 8) containing 5k is available, the remaining pages which contain - * this record are pending AIO return: - *
-        * call       dsize
-        * no.  dsize avail data ptr     Return   Comment
-        * ----+-----+-----+------------+--------+--------------------------------------------------
-        * 1    30k   5k    base_ptr+85k SUCCESS  Initial call, read first 5k
-        * 2    30k   0k    base_ptr+90k AIO_WAIT AIO still pending; no further pages avail
-        * 3    30k   10k   base_ptr+90k SUCCESS  AIO now returned; now read till end of page cache
-        * 4    30k   15k   base_ptr     SUCCESS  data_ptr now pointing to start of page cache
-        * 
- * - * \param rid Reference that returns the record ID (rid) - * \param dsize Reference that returns the total data size of the record data . - * \param dsize_avail Reference that returns the amount of the data that is available for - * consumption. - * \param data Pointer to data pointer which will point to the first byte of the next record - * data. - * \param auto_discard If true, automatically discard the record being read if - * the entire record is available (i.e. dsize == dsize_avail). Otherwise - * discard_next_data_record() must be explicitly called. - * - * \exception TODO - * - // *** NOT YET IMPLEMENTED *** - iores get_data_record(const u_int64_t& rid, const std::size_t& dsize, - const std::size_t& dsize_avail, const void** const data, bool auto_discard = false); - */ - - /* TODO - ** - * \brief Discard (skip) next record to be read without reading or retrieving it. - * - * \exception TODO - * - // *** NOT YET IMPLEMENTED *** - iores discard_data_record(data_tok* const dtokp); - */ - - /** - * \brief Reads data from the journal. It is the responsibility of the reader to free - * the memory that is allocated through this call - see below for details. - * - * Reads the next non-dequeued data record from the journal. - * - * Note that this call allocates memory into which the data and XID are copied. It - * is the responsibility of the caller to free this memory. The memory for the data and - * XID are allocated in a single call, and the XID precedes the data in the memory space. - * Thus, where an XID exists, freeing the XID pointer will free both the XID and data memory. - * However, if an XID does not exist for the message, the XID pointer xidpp is set to NULL, - * and it is the data pointer datapp that must be freed. Should neither an XID nor data be - * present (ie an empty record), then no memory is allocated, and both pointers will be NULL. - * In this case, there is no need to free memory. - * - * TODO: Fix this lousy interface. The caller should NOT be required to clean up these - * pointers! Rather use a struct, or better still, let the data token carry the data and - * xid pointers and lengths, and have the data token both allocate and delete. - * - * \param datapp Pointer to pointer that will be set to point to memory allocated and - * containing the data. Will be set to NULL if the call fails or there is no data - * in the record. - * \param dsize Ref that will be set to the size of the data. Will be set to 0 if the call - * fails or if there is no data in the record. - * \param xidpp Pointer to pointer that will be set to point to memory allocated and - * containing the XID. Will be set to NULL if the call fails or there is no XID attached - * to this record. - * \param xidsize Ref that will be set to the size of the XID. - * \param transient Ref that will be set true if record is transient. - * \param external Ref that will be set true if record is external. In this case, the data - * pointer datapp will be set to NULL, but dsize will contain the size of the data. - * NOTE: If there is an xid, then xidpp must be freed. - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param ignore_pending_txns When false (default), if the next record to be read is locked - * by a pending transaction, the read fails with RHM_IORES_TXPENDING. However, if set - * to true, then locks are ignored. This is required for reading of the Transaction - * Prepared List (TPL) which may have its entries locked, but may be read from - * time-to-time, and needs all its records (locked and unlocked) to be available. - * - * \exception TODO - */ - iores read_data_record(void** const datapp, std::size_t& dsize, void** const xidpp, - std::size_t& xidsize, bool& transient, bool& external, data_tok* const dtokp, - bool ignore_pending_txns = false); - - /** - * \brief Dequeues (marks as no longer needed) data record in journal. - * - * Dequeues (marks as no longer needed) data record in journal. Note that it is possible - * to use the same data token instance used to enqueue this data; it contains the record ID - * needed to correctly mark this data as dequeued in the journal. Otherwise the RID of the - * record to be dequeued and the write state of ENQ must be manually set in a new or reset - * instance of data_tok. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param txn_coml_commit Only used for preparedXID journal. When used for dequeueing - * prepared XID list items, sets whether the complete() was called in commit or abort - * mode. - * - * \exception TODO - */ - iores dequeue_data_record(data_tok* const dtokp, const bool txn_coml_commit = false); - - /** - * \brief Dequeues (marks as no longer needed) data record in journal. - * - * Dequeues (marks as no longer needed) data record in journal as part of a transaction. - * Note that it is possible to use the same data token instance used to enqueue this data; - * it contains the RID needed to correctly mark this data as dequeued in the journal. - * Otherwise the RID of the record to be dequeued and the write state of ENQ must be - * manually set in a new or reset instance of data_tok. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param xid String containing xid. An empty string (i.e. length=0) will be considered - * non-transactional. - * \param txn_coml_commit Only used for preparedXID journal. When used for dequeueing - * prepared XID list items, sets whether the complete() was called in commit or abort - * mode. - * - * \exception TODO - */ - iores dequeue_txn_data_record(data_tok* const dtokp, const std::string& xid, const bool txn_coml_commit = false); - - /** - * \brief Abort the transaction for all records enqueued or dequeued with the matching xid. - * - * Abort the transaction for all records enqueued with the matching xid. All enqueued records - * are effectively deleted from the journal, and can not be read. All dequeued records remain - * as though they had never been dequeued. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param xid String containing xid. - * - * \exception TODO - */ - iores txn_abort(data_tok* const dtokp, const std::string& xid); - - /** - * \brief Commit the transaction for all records enqueued or dequeued with the matching xid. - * - * Commit the transaction for all records enqueued with the matching xid. All enqueued - * records are effectively released for reading and dequeueing. All dequeued records are - * removed and can no longer be accessed. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param xid String containing xid. - * - * \exception TODO - */ - iores txn_commit(data_tok* const dtokp, const std::string& xid); - - /** - * \brief Check whether all the enqueue records for the given xid have reached disk. - * - * \param xid String containing xid. - * - * \exception TODO - */ - bool is_txn_synced(const std::string& xid); - - /** - * \brief Forces a check for returned AIO write events. - * - * Forces a check for returned AIO write events. This is normally performed by enqueue() and - * dequeue() operations, but if these operations cease, then this call needs to be made to - * force the processing of any outstanding AIO operations. - */ - int32_t get_wr_events(timespec* const timeout); - - /** - * \brief Forces a check for returned AIO read events. - * - * Forces a check for returned AIO read events. This is normally performed by read_data() - * operations, but if these operations cease, then this call needs to be made to force the - * processing of any outstanding AIO operations. - */ - int32_t get_rd_events(timespec* const timeout); - - /** - * \brief Stop the journal from accepting any further requests to read or write data. - * - * This operation is used to stop the journal. This is the normal mechanism for bringing the - * journal to an orderly stop. Any outstanding AIO operations or partially written pages in - * the write page cache will by flushed and will complete. - * - * Note: The journal cannot be restarted without either initializing it or restoring - * it. - * - * \param block_till_aio_cmpl If true, will block the thread while waiting for all - * outstanding AIO operations to complete. - */ - void stop(const bool block_till_aio_cmpl = false); - - /** - * \brief Force a flush of the write page cache, creating a single AIO write operation. - */ - iores flush(const bool block_till_aio_cmpl = false); - - inline u_int32_t get_enq_cnt() const { return _emap.size(); } - - inline u_int32_t get_wr_aio_evt_rem() const { slock l(_wr_mutex); return _wmgr.get_aio_evt_rem(); } - - inline u_int32_t get_rd_aio_evt_rem() const { return _rmgr.get_aio_evt_rem(); } - - inline u_int32_t get_wr_outstanding_aio_dblks() const - { return _wrfc.aio_outstanding_dblks(); } - - inline u_int32_t get_wr_outstanding_aio_dblks(u_int16_t lfid) const - { return _lpmgr.get_fcntlp(lfid)->wr_aio_outstanding_dblks(); } - - inline u_int32_t get_rd_outstanding_aio_dblks() const - { return _rrfc.aio_outstanding_dblks(); } - - inline u_int32_t get_rd_outstanding_aio_dblks(u_int16_t lfid) const - { return _lpmgr.get_fcntlp(lfid)->rd_aio_outstanding_dblks(); } - - inline u_int16_t get_rd_fid() const { return _rrfc.index(); } - inline u_int16_t get_wr_fid() const { return _wrfc.index(); } - u_int16_t get_earliest_fid(); - - /** - * \brief Check if a particular rid is enqueued. Note that this function will return - * false if the rid is transactionally enqueued and is not committed, or if it is - * locked (i.e. transactionally dequeued, but the dequeue has not been committed). - */ - inline bool is_enqueued(const u_int64_t rid, bool ignore_lock = false) - { return _emap.is_enqueued(rid, ignore_lock); } - inline bool is_locked(const u_int64_t rid) - { if (_emap.is_enqueued(rid, true) < enq_map::EMAP_OK) return false; return _emap.is_locked(rid) == enq_map::EMAP_TRUE; } - inline void enq_rid_list(std::vector& rids) { _emap.rid_list(rids); } - inline void enq_xid_list(std::vector& xids) { _tmap.xid_list(xids); } - inline u_int32_t get_open_txn_cnt() const { return _tmap.size(); } - // TODO Make this a const, but txn_map must support const first. - inline txn_map& get_txn_map() { return _tmap; } - - /** - * \brief Check if the journal is stopped. - * - * \return true if the jouranl is stopped; - * false otherwise. - */ - inline bool is_stopped() { return _stop_flag; } - - /** - * \brief Check if the journal is ready to read and write data. - * - * Checks if the journal is ready to read and write data. This function will return - * true if the journal has been either initialized or restored, and the stop() - * function has not been called since the initialization. - * - * Note that the journal may also be stopped if an internal error occurs (such as running out - * of data journal file space). - * - * \return true if the journal is ready to read and write data; - * false otherwise. - */ - inline bool is_ready() const { return _init_flag && !_stop_flag; } - - inline bool is_read_only() const { return _readonly_flag; } - - /** - * \brief Get the journal directory. - * - * This returns the journal directory as set during initialization. This is the directory - * into which the journal files will be written. - */ - inline const std::string& dirname() const { return _jdir.dirname(); } - - /** - * \brief Get the journal base filename. - * - * Get the journal base filename as set during initialization. This is the prefix used in all - * journal files of this instance. Note that if more than one instance of the journal shares - * the same directory, their base filenames MUST be different or else the instances - * will overwrite one another. - */ - inline const std::string& base_filename() const { return _base_filename; } - - inline u_int16_t num_jfiles() const { return _lpmgr.num_jfiles(); } - - inline fcntl* get_fcntlp(const u_int16_t lfid) const { return _lpmgr.get_fcntlp(lfid); } - - inline u_int32_t jfsize_sblks() const { return _jfsize_sblks; } - - // Logging - virtual void log(log_level level, const std::string& log_stmt) const; - virtual void log(log_level level, const char* const log_stmt) const; - - // FIXME these are _rmgr to _wmgr interactions, remove when _rmgr contains ref to _wmgr: - void chk_wr_frot(); - inline u_int32_t unflushed_dblks() { return _wmgr.unflushed_dblks(); } - void fhdr_wr_sync(const u_int16_t lid); - inline u_int32_t wr_subm_cnt_dblks(const u_int16_t lfid) const { return _lpmgr.get_fcntlp(lfid)->wr_subm_cnt_dblks(); } - - // Management instrumentation callbacks - inline virtual void instr_incr_outstanding_aio_cnt() {} - inline virtual void instr_decr_outstanding_aio_cnt() {} - - /** - * /brief Static function for creating new fcntl objects for use with obj_arr. - */ - static fcntl* new_fcntl(jcntl* const jcp, const u_int16_t lid, const u_int16_t fid, const rcvdat* const rdp); - - protected: - static bool _init; - static bool init_statics(); - - /** - * \brief Check status of journal before allowing write operations. - */ - void check_wstatus(const char* fn_name) const; - - /** - * \brief Check status of journal before allowing read operations. - */ - void check_rstatus(const char* fn_name) const; - - /** - * \brief Write info file <basefilename>.jinf to disk - */ - void write_infofile() const; - - /** - * \brief Call that blocks while waiting for all outstanding AIOs to complete - */ - void aio_cmpl_wait(); - - /** - * \brief Call that blocks until at least one message returns; used to wait for - * AIO wait conditions to clear. - */ - bool handle_aio_wait(const iores res, iores& resout, const data_tok* dtp); - - /** - * \brief Analyze journal for recovery. - */ - void rcvr_janalyze(rcvdat& rd, const std::vector* prep_txn_list_ptr); - - bool rcvr_get_next_record(u_int16_t& fid, std::ifstream* ifsp, bool& lowi, rcvdat& rd); - - bool decode(jrec& rec, u_int16_t& fid, std::ifstream* ifsp, std::size_t& cum_size_read, - rec_hdr& h, bool& lowi, rcvdat& rd, std::streampos& rec_offset); - - bool jfile_cycle(u_int16_t& fid, std::ifstream* ifsp, bool& lowi, rcvdat& rd, - const bool jump_fro); - - bool check_owi(const u_int16_t fid, rec_hdr& h, bool& lowi, rcvdat& rd, - std::streampos& read_pos); - - void check_journal_alignment(const u_int16_t fid, std::streampos& rec_offset, rcvdat& rd); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_jcntl_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jdir.h b/cpp/src/qpid/legacystore/jrnl/jdir.h new file mode 100644 index 0000000000..364be32e56 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/jdir.h @@ -0,0 +1,379 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file jdir.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::jdir (%journal data + * directory), used for controlling and manipulating %journal data + * directories and files. See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_jdir_hpp +#define mrg_journal_jdir_hpp + +namespace mrg +{ +namespace journal +{ +class jdir; +} +} + +#include "jrnl/jinf.hpp" +#include + +namespace mrg +{ +namespace journal +{ + + /** + * \class jdir + * \brief Class to manage the %journal directory + */ + class jdir + { + private: + std::string _dirname; + std::string _base_filename; + + public: + + /** + * \brief Sole constructor + * + * \param dirname Name of directory to be managed. + * \param base_filename Filename root used in the creation of %journal files + * and sub-directories. + */ + jdir(const std::string& dirname, const std::string& base_filename); + + virtual ~jdir(); + + + /** + * \brief Create %journal directory as set in the dirname parameter of the constructor. + * Recursive creation is supported. + * + * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. + */ + void create_dir(); + + /** + * \brief Static function to create a directory. Recursive creation is supported. + * + * \param dirname C-string containing name of directory. + * + * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. + */ + static void create_dir(const char* dirname); + + /** + * \brief Static function to create a directory. Recursive creation is supported. + * + * \param dirname String containing name of directory. + * + * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. + */ + static void create_dir(const std::string& dirname); + + + /** + * \brief Clear the %journal directory of files matching the base filename + * by moving them into a subdirectory. This fn uses the dirname and base_filename + * that were set on construction. + * + * \param create_flag If set, create dirname if it is non-existent, otherwise throw + * exception. + * + * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. + * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup + * directory failed. + * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. + */ + void clear_dir(const bool create_flag = true); + + /** + * \brief Clear the directory dirname of %journal files matching base_filename + * by moving them into a subdirectory. + * + * \param dirname C-string containing name of %journal directory. + * \param base_filename C-string containing base filename of %journal files to be matched + * for moving into subdirectory. + * \param create_flag If set, create dirname if it is non-existent, otherwise throw + * exception + * + * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. + * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup + * directory failed. + * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. + */ + static void clear_dir(const char* dirname, const char* base_filename, + const bool create_flag = true); + + /** + * \brief Clear the directory dirname of %journal files matching base_filename + * by moving them into a subdirectory. + * + * \param dirname String containing name of %journal directory. + * \param base_filename String containing base filename of %journal files to be matched + * for moving into subdirectory. + * \param create_flag If set, create dirname if it is non-existent, otherwise throw + * exception + * + * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. + * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup + * directory failed. + * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. + */ + static void clear_dir(const std::string& dirname, const std::string& base_filename, + const bool create_flag = true); + + + + /** + * \brief Move (push down) the directory target_dir located in directory dirname into a backup directory + * named _bak_dir_base.XXXX (note prepended underscore), where XXXX is an increasing hex serial number + * starting at 0000. + * + * \param dirname Full path to directory containing directory to be pushed down. + * \param target_dir Name of directory in dirname to be pushed down. + * \param bak_dir_base Base name for backup directory to be created in dirname, into which target_dir will be moved. + * \return Name of backup dir into which target_dir was pushed. + */ + static std::string push_down(const std::string& dirname, const std::string& target_dir, const std::string& bak_dir_base); + + + /** + * \brief Verify that dirname is a valid %journal directory. + * + * The validation reads the .%jinf file, and using this information verifies that all the expected %journal + * (.jdat) files are present. + * + * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory + * \exception jerrno::JERR_JDIR_STAT Could not stat dirname + * \exception jerrno::JERR__FILEIO Error reading %jinf file + * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file + * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing + */ + void verify_dir(); + + /** + * \brief Verify that dirname is a valid %journal directory. + * + * The validation reads the .%jinf file, and using this information verifies that all the expected %journal + * (.jdat) files are present. + * + * \param dirname C-string containing name of %journal directory. + * \param base_filename C-string containing base filename of %journal files to be matched for moving into sub-directory. + * + * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory + * \exception jerrno::JERR_JDIR_STAT Could not stat dirname + * \exception jerrno::JERR__FILEIO Error reading %jinf file + * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file + * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing + */ + static void verify_dir(const char* dirname, const char* base_filename); + + /** + * \brief Verify that dirname is a valid %journal directory. + * + * The validation reads the .%jinf file, and using this information verifies that all the expected %journal + * (.jdat) files are present. + * + * \param dirname String containing name of %journal directory. + * \param base_filename String containing base filename of %journal files to be matched for moving into sub-directory. + * + * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory + * \exception jerrno::JERR_JDIR_STAT Could not stat dirname + * \exception jerrno::JERR__FILEIO Error reading %jinf file + * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file + * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing + */ + static void verify_dir(const std::string& dirname, const std::string& base_filename); + + /** + * \brief Delete the %journal directory and all files and sub--directories that it may + * contain. This is equivilent of rm -rf. + * + * FIXME: links are not handled correctly. + * + * \param children_only If true, delete only children of dirname, but leave dirname itself. + * + * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. + * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. + * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. + * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. + * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. + * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. + */ + void delete_dir(bool children_only = false ); + + /** + * \brief Delete the %journal directory and all files and sub--directories that it may + * contain. This is equivilent of rm -rf. + * + * FIXME: links are not handled correctly. + * + * \param dirname C-string containing name of directory to be deleted. + * \param children_only If true, delete only children of dirname, but leave dirname itself. + * + * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. + * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. + * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. + * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. + * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. + * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. + */ + static void delete_dir(const char* dirname, bool children_only = false); + + /** + * \brief Delete the %journal directory and all files and sub--directories that it may + * contain. This is equivilent of rm -rf. + * + * FIXME: links are not handled correctly. + * + * \param dirname String containing name of directory to be deleted. + * \param children_only If true, delete only children of dirname, but leave dirname itself. + * + * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. + * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. + * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. + * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. + * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. + * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. + */ + static void delete_dir(const std::string& dirname, bool children_only = false); + + /** + * \brief Create bakup directory that is next in sequence and move all %journal files + * matching base_filename into it. + * + * In directory dirname, search for existing backup directory using pattern + * "_basename.bak.XXXX" where XXXX is a hexadecimal sequence, and create next directory + * based on highest number found. Move all %journal files which match the base_fileaname + * parameter into this new backup directory. + * + * \param dirname String containing name of %journal directory. + * \param base_filename String containing base filename of %journal files to be matched + * for moving into subdirectory. + * + * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. + * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. + * \exception jerrno::JERR_JDIR_MKDIR The backup directory could not be deleted. + */ + static std::string create_bak_dir(const std::string& dirname, + const std::string& base_filename); + + /** + * \brief Return the directory name as a string. + */ + inline const std::string& dirname() const { return _dirname; } + + /** + * \brief Return the %journal base filename name as a string. + */ + inline const std::string& base_filename() const { return _base_filename; } + + /** + * \brief Test whether the named file is a directory. + * + * \param name Name of file to be tested. + * \return true if the named file is a directory; false + * otherwise. + * \exception jerrno::JERR_JDIR_STAT Could not stat name. + */ + static bool is_dir(const char* name); + + /** + * \brief Test whether the named file is a directory. + * + * \param name Name of file to be tested. + * \return true if the named file is a directory; false + * otherwise. + * \exception jerrno::JERR_JDIR_STAT Could not stat name. + */ + static bool is_dir(const std::string& name); + + + /** + * \brief Test whether the named entity exists on the filesystem. + * + * If stat() fails with error ENOENT, then this will return false. If + * stat() succeeds, then true is returned, irrespective of the file type. + * If stat() fails with any other error, an exception is thrown. + * + * \param name Name of entity to be tested. + * \return true if the named entity exists; false + * otherwise. + * \exception jerrno::JERR_JDIR_STAT Could not stat name. + */ + static bool exists(const char* name); + + /** + * \brief Test whether the named entity exists on the filesystem. + * + * If stat() fails with error ENOENT, then this will return false. If + * stat() succeeds, then true is returned, irrespective of the file type. + * If stat() fails with any other error, an exception is thrown. + * + * \param name Name of entity to be tested. + * \return true if the named entity exists; false + * otherwise. + * \exception jerrno::JERR_JDIR_STAT Could not stat name. + */ + static bool exists(const std::string& name); + + /** + * \brief Stream operator + */ + friend std::ostream& operator<<(std::ostream& os, const jdir& jdir); + + /** + * \brief Stream operator + */ + friend std::ostream& operator<<(std::ostream& os, const jdir* jdirPtr); + + private: + /** + * \brief Check for error, if non-zero close DIR handle and throw JERR_JDIR_READDIR + * + * \exception jerrno::JERR_JDIR_READDIR Error while reading contents of dir. + */ + static void check_err(const int err_num, DIR* dir, const std::string& dir_name, const std::string& fn_name); + + /** + * \brief Close a DIR handle, throw JERR_JDIR_CLOSEDIR if error occurs during close + * + * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. + */ + static void close_dir(DIR* dir, const std::string& dir_name, const std::string& fn_name); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_jdir_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jdir.hpp b/cpp/src/qpid/legacystore/jrnl/jdir.hpp deleted file mode 100644 index 364be32e56..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/jdir.hpp +++ /dev/null @@ -1,379 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file jdir.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::jdir (%journal data - * directory), used for controlling and manipulating %journal data - * directories and files. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_jdir_hpp -#define mrg_journal_jdir_hpp - -namespace mrg -{ -namespace journal -{ -class jdir; -} -} - -#include "jrnl/jinf.hpp" -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class jdir - * \brief Class to manage the %journal directory - */ - class jdir - { - private: - std::string _dirname; - std::string _base_filename; - - public: - - /** - * \brief Sole constructor - * - * \param dirname Name of directory to be managed. - * \param base_filename Filename root used in the creation of %journal files - * and sub-directories. - */ - jdir(const std::string& dirname, const std::string& base_filename); - - virtual ~jdir(); - - - /** - * \brief Create %journal directory as set in the dirname parameter of the constructor. - * Recursive creation is supported. - * - * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. - */ - void create_dir(); - - /** - * \brief Static function to create a directory. Recursive creation is supported. - * - * \param dirname C-string containing name of directory. - * - * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. - */ - static void create_dir(const char* dirname); - - /** - * \brief Static function to create a directory. Recursive creation is supported. - * - * \param dirname String containing name of directory. - * - * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. - */ - static void create_dir(const std::string& dirname); - - - /** - * \brief Clear the %journal directory of files matching the base filename - * by moving them into a subdirectory. This fn uses the dirname and base_filename - * that were set on construction. - * - * \param create_flag If set, create dirname if it is non-existent, otherwise throw - * exception. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup - * directory failed. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - void clear_dir(const bool create_flag = true); - - /** - * \brief Clear the directory dirname of %journal files matching base_filename - * by moving them into a subdirectory. - * - * \param dirname C-string containing name of %journal directory. - * \param base_filename C-string containing base filename of %journal files to be matched - * for moving into subdirectory. - * \param create_flag If set, create dirname if it is non-existent, otherwise throw - * exception - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup - * directory failed. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - static void clear_dir(const char* dirname, const char* base_filename, - const bool create_flag = true); - - /** - * \brief Clear the directory dirname of %journal files matching base_filename - * by moving them into a subdirectory. - * - * \param dirname String containing name of %journal directory. - * \param base_filename String containing base filename of %journal files to be matched - * for moving into subdirectory. - * \param create_flag If set, create dirname if it is non-existent, otherwise throw - * exception - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup - * directory failed. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - static void clear_dir(const std::string& dirname, const std::string& base_filename, - const bool create_flag = true); - - - - /** - * \brief Move (push down) the directory target_dir located in directory dirname into a backup directory - * named _bak_dir_base.XXXX (note prepended underscore), where XXXX is an increasing hex serial number - * starting at 0000. - * - * \param dirname Full path to directory containing directory to be pushed down. - * \param target_dir Name of directory in dirname to be pushed down. - * \param bak_dir_base Base name for backup directory to be created in dirname, into which target_dir will be moved. - * \return Name of backup dir into which target_dir was pushed. - */ - static std::string push_down(const std::string& dirname, const std::string& target_dir, const std::string& bak_dir_base); - - - /** - * \brief Verify that dirname is a valid %journal directory. - * - * The validation reads the .%jinf file, and using this information verifies that all the expected %journal - * (.jdat) files are present. - * - * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname - * \exception jerrno::JERR__FILEIO Error reading %jinf file - * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file - * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing - */ - void verify_dir(); - - /** - * \brief Verify that dirname is a valid %journal directory. - * - * The validation reads the .%jinf file, and using this information verifies that all the expected %journal - * (.jdat) files are present. - * - * \param dirname C-string containing name of %journal directory. - * \param base_filename C-string containing base filename of %journal files to be matched for moving into sub-directory. - * - * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname - * \exception jerrno::JERR__FILEIO Error reading %jinf file - * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file - * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing - */ - static void verify_dir(const char* dirname, const char* base_filename); - - /** - * \brief Verify that dirname is a valid %journal directory. - * - * The validation reads the .%jinf file, and using this information verifies that all the expected %journal - * (.jdat) files are present. - * - * \param dirname String containing name of %journal directory. - * \param base_filename String containing base filename of %journal files to be matched for moving into sub-directory. - * - * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname - * \exception jerrno::JERR__FILEIO Error reading %jinf file - * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file - * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing - */ - static void verify_dir(const std::string& dirname, const std::string& base_filename); - - /** - * \brief Delete the %journal directory and all files and sub--directories that it may - * contain. This is equivilent of rm -rf. - * - * FIXME: links are not handled correctly. - * - * \param children_only If true, delete only children of dirname, but leave dirname itself. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. - * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. - * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. - */ - void delete_dir(bool children_only = false ); - - /** - * \brief Delete the %journal directory and all files and sub--directories that it may - * contain. This is equivilent of rm -rf. - * - * FIXME: links are not handled correctly. - * - * \param dirname C-string containing name of directory to be deleted. - * \param children_only If true, delete only children of dirname, but leave dirname itself. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. - * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. - * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. - */ - static void delete_dir(const char* dirname, bool children_only = false); - - /** - * \brief Delete the %journal directory and all files and sub--directories that it may - * contain. This is equivilent of rm -rf. - * - * FIXME: links are not handled correctly. - * - * \param dirname String containing name of directory to be deleted. - * \param children_only If true, delete only children of dirname, but leave dirname itself. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. - * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. - * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. - */ - static void delete_dir(const std::string& dirname, bool children_only = false); - - /** - * \brief Create bakup directory that is next in sequence and move all %journal files - * matching base_filename into it. - * - * In directory dirname, search for existing backup directory using pattern - * "_basename.bak.XXXX" where XXXX is a hexadecimal sequence, and create next directory - * based on highest number found. Move all %journal files which match the base_fileaname - * parameter into this new backup directory. - * - * \param dirname String containing name of %journal directory. - * \param base_filename String containing base filename of %journal files to be matched - * for moving into subdirectory. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_MKDIR The backup directory could not be deleted. - */ - static std::string create_bak_dir(const std::string& dirname, - const std::string& base_filename); - - /** - * \brief Return the directory name as a string. - */ - inline const std::string& dirname() const { return _dirname; } - - /** - * \brief Return the %journal base filename name as a string. - */ - inline const std::string& base_filename() const { return _base_filename; } - - /** - * \brief Test whether the named file is a directory. - * - * \param name Name of file to be tested. - * \return true if the named file is a directory; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool is_dir(const char* name); - - /** - * \brief Test whether the named file is a directory. - * - * \param name Name of file to be tested. - * \return true if the named file is a directory; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool is_dir(const std::string& name); - - - /** - * \brief Test whether the named entity exists on the filesystem. - * - * If stat() fails with error ENOENT, then this will return false. If - * stat() succeeds, then true is returned, irrespective of the file type. - * If stat() fails with any other error, an exception is thrown. - * - * \param name Name of entity to be tested. - * \return true if the named entity exists; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool exists(const char* name); - - /** - * \brief Test whether the named entity exists on the filesystem. - * - * If stat() fails with error ENOENT, then this will return false. If - * stat() succeeds, then true is returned, irrespective of the file type. - * If stat() fails with any other error, an exception is thrown. - * - * \param name Name of entity to be tested. - * \return true if the named entity exists; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool exists(const std::string& name); - - /** - * \brief Stream operator - */ - friend std::ostream& operator<<(std::ostream& os, const jdir& jdir); - - /** - * \brief Stream operator - */ - friend std::ostream& operator<<(std::ostream& os, const jdir* jdirPtr); - - private: - /** - * \brief Check for error, if non-zero close DIR handle and throw JERR_JDIR_READDIR - * - * \exception jerrno::JERR_JDIR_READDIR Error while reading contents of dir. - */ - static void check_err(const int err_num, DIR* dir, const std::string& dir_name, const std::string& fn_name); - - /** - * \brief Close a DIR handle, throw JERR_JDIR_CLOSEDIR if error occurs during close - * - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - static void close_dir(DIR* dir, const std::string& dir_name, const std::string& fn_name); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_jdir_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jerrno.h b/cpp/src/qpid/legacystore/jrnl/jerrno.h new file mode 100644 index 0000000000..3709e3a651 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/jerrno.h @@ -0,0 +1,173 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file jerrno.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::jerrno (journal error + * codes). See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_jerrno_hpp +#define mrg_journal_jerrno_hpp + +namespace mrg +{ +namespace journal +{ +class jerrno; +} +} + +#include +#include +#include + +namespace mrg +{ +namespace journal +{ + + /** + * \class jerrno + * \brief Class containing static error definitions and static map for error messages. + */ + class jerrno + { + static std::map _err_map; ///< Map of error messages + static std::map::iterator _err_map_itr; ///< Iterator + static bool _initialized; ///< Dummy flag, used to initialise map. + + public: + // generic errors + static const u_int32_t JERR__MALLOC; ///< Buffer memory allocation failed + static const u_int32_t JERR__UNDERFLOW; ///< Underflow error + static const u_int32_t JERR__NINIT; ///< Operation on uninitialized class + static const u_int32_t JERR__AIO; ///< AIO failure + static const u_int32_t JERR__FILEIO; ///< File read or write failure + static const u_int32_t JERR__RTCLOCK; ///< Reading real-time clock failed + static const u_int32_t JERR__PTHREAD; ///< pthread failure + static const u_int32_t JERR__TIMEOUT; ///< Timeout waiting for an event + static const u_int32_t JERR__UNEXPRESPONSE; ///< Unexpected response to call or event + static const u_int32_t JERR__RECNFOUND; ///< Record not found + static const u_int32_t JERR__NOTIMPL; ///< Not implemented + + // class jcntl + static const u_int32_t JERR_JCNTL_STOPPED; ///< Operation on stopped journal + static const u_int32_t JERR_JCNTL_READONLY; ///< Write operation on read-only journal + static const u_int32_t JERR_JCNTL_AIOCMPLWAIT; ///< Timeout waiting for AIOs to complete + static const u_int32_t JERR_JCNTL_UNKNOWNMAGIC; ///< Found record with unknown magic + static const u_int32_t JERR_JCNTL_NOTRECOVERED; ///< Req' recover() to be called first + static const u_int32_t JERR_JCNTL_RECOVERJFULL; ///< Journal data files full, cannot write + static const u_int32_t JERR_JCNTL_OWIMISMATCH; ///< OWI change found in unexpected location + + // class jdir + static const u_int32_t JERR_JDIR_NOTDIR; ///< Exists but is not a directory + static const u_int32_t JERR_JDIR_MKDIR; ///< Directory creation failed + static const u_int32_t JERR_JDIR_OPENDIR; ///< Directory open failed + static const u_int32_t JERR_JDIR_READDIR; ///< Directory read failed + static const u_int32_t JERR_JDIR_CLOSEDIR; ///< Directory close failed + static const u_int32_t JERR_JDIR_RMDIR; ///< Directory delete failed + static const u_int32_t JERR_JDIR_NOSUCHFILE; ///< File does not exist + static const u_int32_t JERR_JDIR_FMOVE; ///< File move failed + static const u_int32_t JERR_JDIR_STAT; ///< File stat failed + static const u_int32_t JERR_JDIR_UNLINK; ///< File delete failed + static const u_int32_t JERR_JDIR_BADFTYPE; ///< Bad or unknown file type (stat mode) + + // class fcntl + static const u_int32_t JERR_FCNTL_OPENWR; ///< Unable to open file for write + static const u_int32_t JERR_FCNTL_WRITE; ///< Unable to write to file + static const u_int32_t JERR_FCNTL_CLOSE; ///< File close failed + static const u_int32_t JERR_FCNTL_FILEOFFSOVFL; ///< Increased offset past file size + static const u_int32_t JERR_FCNTL_CMPLOFFSOVFL; ///< Increased cmpl offs past subm offs + static const u_int32_t JERR_FCNTL_RDOFFSOVFL; ///< Increased read offs past write offs + + // class lfmgr + static const u_int32_t JERR_LFMGR_BADAEFNUMLIM; ///< Bad auto-expand file number limit + static const u_int32_t JERR_LFMGR_AEFNUMLIMIT; ///< Exceeded auto-expand file number limit + static const u_int32_t JERR_LFMGR_AEDISABLED; ///< Attempted to expand with auto-expand disabled + + // class rrfc + static const u_int32_t JERR_RRFC_OPENRD; ///< Unable to open file for read + + // class jrec, enq_rec, deq_rec, txn_rec + static const u_int32_t JERR_JREC_BADRECHDR; ///< Invalid data record header + static const u_int32_t JERR_JREC_BADRECTAIL; ///< Invalid data record tail + + // class wmgr + static const u_int32_t JERR_WMGR_BADPGSTATE; ///< Page buffer in illegal state. + static const u_int32_t JERR_WMGR_BADDTOKSTATE; ///< Data token in illegal state. + static const u_int32_t JERR_WMGR_ENQDISCONT; ///< Enq. new dtok when previous part compl. + static const u_int32_t JERR_WMGR_DEQDISCONT; ///< Deq. new dtok when previous part compl. + static const u_int32_t JERR_WMGR_DEQRIDNOTENQ; ///< Deq. rid not enqueued + + // class rmgr + static const u_int32_t JERR_RMGR_UNKNOWNMAGIC; ///< Found record with unknown magic + static const u_int32_t JERR_RMGR_RIDMISMATCH; ///< RID mismatch between rec and dtok + //static const u_int32_t JERR_RMGR_FIDMISMATCH; ///< FID mismatch between emap and rrfc + static const u_int32_t JERR_RMGR_ENQSTATE; ///< Attempted read when wstate not ENQ + static const u_int32_t JERR_RMGR_BADRECTYPE; ///< Attempted op on incorrect rec type + + // class data_tok + static const u_int32_t JERR_DTOK_ILLEGALSTATE; ///< Attempted to change to illegal state +// static const u_int32_t JERR_DTOK_RIDNOTSET; ///< Record ID not set + + // class enq_map, txn_map + static const u_int32_t JERR_MAP_DUPLICATE; ///< Attempted to insert using duplicate key + static const u_int32_t JERR_MAP_NOTFOUND; ///< Key not found in map + static const u_int32_t JERR_MAP_LOCKED; ///< rid locked by pending txn + + // class jinf + static const u_int32_t JERR_JINF_CVALIDFAIL; ///< Compatibility validation failure + static const u_int32_t JERR_JINF_NOVALUESTR; ///< No value attr found in jinf file + static const u_int32_t JERR_JINF_BADVALUESTR; ///< Bad format for value attr in jinf file + static const u_int32_t JERR_JINF_JDATEMPTY; ///< Journal data files empty + static const u_int32_t JERR_JINF_TOOMANYFILES; ///< Too many journal data files + static const u_int32_t JERR_JINF_INVALIDFHDR; ///< Invalid file header + static const u_int32_t JERR_JINF_STAT; ///< Error while trying to stat a file + static const u_int32_t JERR_JINF_NOTREGFILE; ///< Target file is not a regular file + static const u_int32_t JERR_JINF_BADFILESIZE; ///< File is of incorrect or unexpected size + static const u_int32_t JERR_JINF_OWIBAD; ///< OWI inconsistent (>1 transition in non-ae journal) + static const u_int32_t JERR_JINF_ZEROLENFILE; ///< Journal info file is zero length (empty). + + // Negative returns for some functions + static const int32_t AIO_TIMEOUT; ///< Timeout waiting for AIO return + static const int32_t LOCK_TAKEN; ///< Attempted to take lock, but it was taken by another thread + /** + * \brief Method to access error message from known error number. + */ + static const char* err_msg(const u_int32_t err_no) throw (); + + private: + /** + * \brief Static function to initialize map. + */ + static bool __init(); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_jerrno_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jerrno.hpp b/cpp/src/qpid/legacystore/jrnl/jerrno.hpp deleted file mode 100644 index 3709e3a651..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/jerrno.hpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file jerrno.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::jerrno (journal error - * codes). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_jerrno_hpp -#define mrg_journal_jerrno_hpp - -namespace mrg -{ -namespace journal -{ -class jerrno; -} -} - -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class jerrno - * \brief Class containing static error definitions and static map for error messages. - */ - class jerrno - { - static std::map _err_map; ///< Map of error messages - static std::map::iterator _err_map_itr; ///< Iterator - static bool _initialized; ///< Dummy flag, used to initialise map. - - public: - // generic errors - static const u_int32_t JERR__MALLOC; ///< Buffer memory allocation failed - static const u_int32_t JERR__UNDERFLOW; ///< Underflow error - static const u_int32_t JERR__NINIT; ///< Operation on uninitialized class - static const u_int32_t JERR__AIO; ///< AIO failure - static const u_int32_t JERR__FILEIO; ///< File read or write failure - static const u_int32_t JERR__RTCLOCK; ///< Reading real-time clock failed - static const u_int32_t JERR__PTHREAD; ///< pthread failure - static const u_int32_t JERR__TIMEOUT; ///< Timeout waiting for an event - static const u_int32_t JERR__UNEXPRESPONSE; ///< Unexpected response to call or event - static const u_int32_t JERR__RECNFOUND; ///< Record not found - static const u_int32_t JERR__NOTIMPL; ///< Not implemented - - // class jcntl - static const u_int32_t JERR_JCNTL_STOPPED; ///< Operation on stopped journal - static const u_int32_t JERR_JCNTL_READONLY; ///< Write operation on read-only journal - static const u_int32_t JERR_JCNTL_AIOCMPLWAIT; ///< Timeout waiting for AIOs to complete - static const u_int32_t JERR_JCNTL_UNKNOWNMAGIC; ///< Found record with unknown magic - static const u_int32_t JERR_JCNTL_NOTRECOVERED; ///< Req' recover() to be called first - static const u_int32_t JERR_JCNTL_RECOVERJFULL; ///< Journal data files full, cannot write - static const u_int32_t JERR_JCNTL_OWIMISMATCH; ///< OWI change found in unexpected location - - // class jdir - static const u_int32_t JERR_JDIR_NOTDIR; ///< Exists but is not a directory - static const u_int32_t JERR_JDIR_MKDIR; ///< Directory creation failed - static const u_int32_t JERR_JDIR_OPENDIR; ///< Directory open failed - static const u_int32_t JERR_JDIR_READDIR; ///< Directory read failed - static const u_int32_t JERR_JDIR_CLOSEDIR; ///< Directory close failed - static const u_int32_t JERR_JDIR_RMDIR; ///< Directory delete failed - static const u_int32_t JERR_JDIR_NOSUCHFILE; ///< File does not exist - static const u_int32_t JERR_JDIR_FMOVE; ///< File move failed - static const u_int32_t JERR_JDIR_STAT; ///< File stat failed - static const u_int32_t JERR_JDIR_UNLINK; ///< File delete failed - static const u_int32_t JERR_JDIR_BADFTYPE; ///< Bad or unknown file type (stat mode) - - // class fcntl - static const u_int32_t JERR_FCNTL_OPENWR; ///< Unable to open file for write - static const u_int32_t JERR_FCNTL_WRITE; ///< Unable to write to file - static const u_int32_t JERR_FCNTL_CLOSE; ///< File close failed - static const u_int32_t JERR_FCNTL_FILEOFFSOVFL; ///< Increased offset past file size - static const u_int32_t JERR_FCNTL_CMPLOFFSOVFL; ///< Increased cmpl offs past subm offs - static const u_int32_t JERR_FCNTL_RDOFFSOVFL; ///< Increased read offs past write offs - - // class lfmgr - static const u_int32_t JERR_LFMGR_BADAEFNUMLIM; ///< Bad auto-expand file number limit - static const u_int32_t JERR_LFMGR_AEFNUMLIMIT; ///< Exceeded auto-expand file number limit - static const u_int32_t JERR_LFMGR_AEDISABLED; ///< Attempted to expand with auto-expand disabled - - // class rrfc - static const u_int32_t JERR_RRFC_OPENRD; ///< Unable to open file for read - - // class jrec, enq_rec, deq_rec, txn_rec - static const u_int32_t JERR_JREC_BADRECHDR; ///< Invalid data record header - static const u_int32_t JERR_JREC_BADRECTAIL; ///< Invalid data record tail - - // class wmgr - static const u_int32_t JERR_WMGR_BADPGSTATE; ///< Page buffer in illegal state. - static const u_int32_t JERR_WMGR_BADDTOKSTATE; ///< Data token in illegal state. - static const u_int32_t JERR_WMGR_ENQDISCONT; ///< Enq. new dtok when previous part compl. - static const u_int32_t JERR_WMGR_DEQDISCONT; ///< Deq. new dtok when previous part compl. - static const u_int32_t JERR_WMGR_DEQRIDNOTENQ; ///< Deq. rid not enqueued - - // class rmgr - static const u_int32_t JERR_RMGR_UNKNOWNMAGIC; ///< Found record with unknown magic - static const u_int32_t JERR_RMGR_RIDMISMATCH; ///< RID mismatch between rec and dtok - //static const u_int32_t JERR_RMGR_FIDMISMATCH; ///< FID mismatch between emap and rrfc - static const u_int32_t JERR_RMGR_ENQSTATE; ///< Attempted read when wstate not ENQ - static const u_int32_t JERR_RMGR_BADRECTYPE; ///< Attempted op on incorrect rec type - - // class data_tok - static const u_int32_t JERR_DTOK_ILLEGALSTATE; ///< Attempted to change to illegal state -// static const u_int32_t JERR_DTOK_RIDNOTSET; ///< Record ID not set - - // class enq_map, txn_map - static const u_int32_t JERR_MAP_DUPLICATE; ///< Attempted to insert using duplicate key - static const u_int32_t JERR_MAP_NOTFOUND; ///< Key not found in map - static const u_int32_t JERR_MAP_LOCKED; ///< rid locked by pending txn - - // class jinf - static const u_int32_t JERR_JINF_CVALIDFAIL; ///< Compatibility validation failure - static const u_int32_t JERR_JINF_NOVALUESTR; ///< No value attr found in jinf file - static const u_int32_t JERR_JINF_BADVALUESTR; ///< Bad format for value attr in jinf file - static const u_int32_t JERR_JINF_JDATEMPTY; ///< Journal data files empty - static const u_int32_t JERR_JINF_TOOMANYFILES; ///< Too many journal data files - static const u_int32_t JERR_JINF_INVALIDFHDR; ///< Invalid file header - static const u_int32_t JERR_JINF_STAT; ///< Error while trying to stat a file - static const u_int32_t JERR_JINF_NOTREGFILE; ///< Target file is not a regular file - static const u_int32_t JERR_JINF_BADFILESIZE; ///< File is of incorrect or unexpected size - static const u_int32_t JERR_JINF_OWIBAD; ///< OWI inconsistent (>1 transition in non-ae journal) - static const u_int32_t JERR_JINF_ZEROLENFILE; ///< Journal info file is zero length (empty). - - // Negative returns for some functions - static const int32_t AIO_TIMEOUT; ///< Timeout waiting for AIO return - static const int32_t LOCK_TAKEN; ///< Attempted to take lock, but it was taken by another thread - /** - * \brief Method to access error message from known error number. - */ - static const char* err_msg(const u_int32_t err_no) throw (); - - private: - /** - * \brief Static function to initialize map. - */ - static bool __init(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_jerrno_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jexception.h b/cpp/src/qpid/legacystore/jrnl/jexception.h new file mode 100644 index 0000000000..33e9563642 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/jexception.h @@ -0,0 +1,142 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file jexception.hpp + * + * Qpid asynchronous store plugin library + * + * Generic journal exception class mrg::journal::jexception (derived + * from class std::exception). Intended to serve as a common exception + * class for all more speicalized exceptions in the message journal. See + * class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_jrnl_exception_hpp +#define mrg_journal_jrnl_exception_hpp + +namespace mrg +{ +namespace journal +{ +class jexception; +} +} + +#include +#include +#include +#include +#include +#include "jrnl/jerrno.hpp" +#include +#include +#include + +// Macro for formatting commom system errors +#define FORMAT_SYSERR(errno) " errno=" << errno << " (" << std::strerror(errno) << ")" + +#define MALLOC_CHK(ptr, var, cls, fn) if(ptr == 0) { \ + clean(); \ + std::ostringstream oss; \ + oss << var << ": malloc() failed: " << FORMAT_SYSERR(errno); \ + throw jexception(jerrno::JERR__MALLOC, oss.str(), cls, fn); \ + } + +// TODO: The following is a temporary bug-tracking aid which forces a core. +// Replace with the commented out version below when BZ484048 is resolved. +#define PTHREAD_CHK(err, pfn, cls, fn) if(err != 0) { \ + std::ostringstream oss; \ + oss << cls << "::" << fn << "(): " << pfn; \ + errno = err; \ + ::perror(oss.str().c_str()); \ + ::abort(); \ + } +/* +#define PTHREAD_CHK(err, pfn, cls, fn) if(err != 0) { \ + std::ostringstream oss; \ + oss << pfn << " failed: " << FORMAT_SYSERR(err); \ + throw jexception(jerrno::JERR__PTHREAD, oss.str(), cls, fn); \ + } +*/ + +#define ASSERT(cond, msg) if(cond == 0) { \ + std::cerr << msg << std::endl; \ + ::abort(); \ + } + +namespace mrg +{ +namespace journal +{ + /** + * \class jexception + * \brief Generic journal exception class + */ + class jexception : public std::exception + { + private: + u_int32_t _err_code; + std::string _additional_info; + std::string _throwing_class; + std::string _throwing_fn; + std::string _what; + void format(); + + public: + jexception() throw (); + + jexception(const u_int32_t err_code) throw (); + + jexception(const char* additional_info) throw (); + jexception(const std::string& additional_info) throw (); + + jexception(const u_int32_t err_code, const char* additional_info) throw (); + jexception(const u_int32_t err_code, const std::string& additional_info) throw (); + + jexception(const u_int32_t err_code, const char* throwing_class, const char* throwing_fn) + throw (); + jexception(const u_int32_t err_code, const std::string& throwing_class, + const std::string& throwing_fn) throw (); + + jexception(const u_int32_t err_code, const char* additional_info, + const char* throwing_class, const char* throwing_fn) throw (); + jexception(const u_int32_t err_code, const std::string& additional_info, + const std::string& throwing_class, const std::string& throwing_fn) throw (); + + virtual ~jexception() throw (); + virtual const char* what() const throw (); // override std::exception::what() + + inline u_int32_t err_code() const throw () { return _err_code; } + inline const std::string additional_info() const throw () { return _additional_info; } + inline const std::string throwing_class() const throw () { return _throwing_class; } + inline const std::string throwing_fn() const throw () { return _throwing_fn; } + + friend std::ostream& operator<<(std::ostream& os, const jexception& je); + friend std::ostream& operator<<(std::ostream& os, const jexception* jePtr); + }; // class jexception + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_jrnl_exception_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jexception.hpp b/cpp/src/qpid/legacystore/jrnl/jexception.hpp deleted file mode 100644 index 33e9563642..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/jexception.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file jexception.hpp - * - * Qpid asynchronous store plugin library - * - * Generic journal exception class mrg::journal::jexception (derived - * from class std::exception). Intended to serve as a common exception - * class for all more speicalized exceptions in the message journal. See - * class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_jrnl_exception_hpp -#define mrg_journal_jrnl_exception_hpp - -namespace mrg -{ -namespace journal -{ -class jexception; -} -} - -#include -#include -#include -#include -#include -#include "jrnl/jerrno.hpp" -#include -#include -#include - -// Macro for formatting commom system errors -#define FORMAT_SYSERR(errno) " errno=" << errno << " (" << std::strerror(errno) << ")" - -#define MALLOC_CHK(ptr, var, cls, fn) if(ptr == 0) { \ - clean(); \ - std::ostringstream oss; \ - oss << var << ": malloc() failed: " << FORMAT_SYSERR(errno); \ - throw jexception(jerrno::JERR__MALLOC, oss.str(), cls, fn); \ - } - -// TODO: The following is a temporary bug-tracking aid which forces a core. -// Replace with the commented out version below when BZ484048 is resolved. -#define PTHREAD_CHK(err, pfn, cls, fn) if(err != 0) { \ - std::ostringstream oss; \ - oss << cls << "::" << fn << "(): " << pfn; \ - errno = err; \ - ::perror(oss.str().c_str()); \ - ::abort(); \ - } -/* -#define PTHREAD_CHK(err, pfn, cls, fn) if(err != 0) { \ - std::ostringstream oss; \ - oss << pfn << " failed: " << FORMAT_SYSERR(err); \ - throw jexception(jerrno::JERR__PTHREAD, oss.str(), cls, fn); \ - } -*/ - -#define ASSERT(cond, msg) if(cond == 0) { \ - std::cerr << msg << std::endl; \ - ::abort(); \ - } - -namespace mrg -{ -namespace journal -{ - /** - * \class jexception - * \brief Generic journal exception class - */ - class jexception : public std::exception - { - private: - u_int32_t _err_code; - std::string _additional_info; - std::string _throwing_class; - std::string _throwing_fn; - std::string _what; - void format(); - - public: - jexception() throw (); - - jexception(const u_int32_t err_code) throw (); - - jexception(const char* additional_info) throw (); - jexception(const std::string& additional_info) throw (); - - jexception(const u_int32_t err_code, const char* additional_info) throw (); - jexception(const u_int32_t err_code, const std::string& additional_info) throw (); - - jexception(const u_int32_t err_code, const char* throwing_class, const char* throwing_fn) - throw (); - jexception(const u_int32_t err_code, const std::string& throwing_class, - const std::string& throwing_fn) throw (); - - jexception(const u_int32_t err_code, const char* additional_info, - const char* throwing_class, const char* throwing_fn) throw (); - jexception(const u_int32_t err_code, const std::string& additional_info, - const std::string& throwing_class, const std::string& throwing_fn) throw (); - - virtual ~jexception() throw (); - virtual const char* what() const throw (); // override std::exception::what() - - inline u_int32_t err_code() const throw () { return _err_code; } - inline const std::string additional_info() const throw () { return _additional_info; } - inline const std::string throwing_class() const throw () { return _throwing_class; } - inline const std::string throwing_fn() const throw () { return _throwing_fn; } - - friend std::ostream& operator<<(std::ostream& os, const jexception& je); - friend std::ostream& operator<<(std::ostream& os, const jexception* jePtr); - }; // class jexception - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_jrnl_exception_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jinf.h b/cpp/src/qpid/legacystore/jrnl/jinf.h new file mode 100644 index 0000000000..0d3c9aa552 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/jinf.h @@ -0,0 +1,133 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file jinf.hpp + * + * Qpid asynchronous store plugin library + * + * This file contains the code for the mrg::journal::jinf class. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_jinf_hpp +#define mrg_journal_jinf_hpp + +#include +#include +#include +#include + +namespace mrg +{ +namespace journal +{ + /** + * \class jinf + * \brief Class to handle the journal information file <basename>.jinf. + */ + class jinf + { + public: + typedef std::vector pfid_list; // pfids + typedef pfid_list::const_iterator pfidl_citr; + + private: + u_int8_t _jver; + std::string _jid; + std::string _jdir; + std::string _base_filename; + std::string _filename; + timespec _ts; + u_int16_t _num_jfiles; + bool _ae; + u_int32_t _ae_max_jfiles; + u_int32_t _jfsize_sblks; + u_int16_t _sblk_size_dblks; + u_int32_t _dblk_size; + u_int32_t _wcache_pgsize_sblks; + u_int16_t _wcache_num_pages; + u_int32_t _rcache_pgsize_sblks; + u_int16_t _rcache_num_pages; + std::tm* _tm_ptr; + bool _valid_flag; + bool _analyzed_flag; + pfid_list _pfid_list; + bool _initial_owi; + bool _frot; + + public: + // constructor for reading existing jinf file + jinf(const std::string& jinf_filename, bool validate_flag); + // constructor for writing jinf file + jinf(const std::string& jid, const std::string& jdir, const std::string& base_filename, + const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles, + const u_int32_t jfsize_sblks, const u_int32_t wcache_pgsize_sblks, const u_int16_t wcache_num_pages, + const timespec& ts); + virtual ~jinf(); + + void validate(); + void analyze(); + void write(); + + inline u_int8_t jver() const { return _jver; } + inline const std::string& jid() const { return _jid; } + inline const std::string& jdir() const { return _jdir; } + inline void set_jdir(const std::string& jdir) { _jdir = jdir; } + inline const std::string& base_filename() const { return _base_filename; } + inline const timespec& ts() const { return _ts; } + inline u_int16_t num_jfiles() const { return _num_jfiles; } + u_int16_t incr_num_jfiles(); + inline bool is_ae() const { return _ae; } + inline u_int16_t ae_max_jfiles() const { return _ae_max_jfiles; } + inline u_int32_t jfsize_sblks() const { return _jfsize_sblks; } + inline u_int16_t sblk_size_dblks() const { return _sblk_size_dblks; } + inline u_int32_t dblk_size() const { return _dblk_size; } + inline u_int32_t wcache_pgsize_sblks() const { return _wcache_pgsize_sblks; } + inline u_int16_t wcache_num_pages() const { return _wcache_num_pages; } + inline u_int32_t rcache_pgsize_sblks() const { return _rcache_pgsize_sblks; } + inline u_int16_t rcache_num_pages() const { return _rcache_num_pages; } + u_int16_t get_first_pfid(); + u_int16_t get_last_pfid(); + pfid_list& get_pfid_list(); + void get_normalized_pfid_list(pfid_list& pfid_list); + bool get_initial_owi(); + bool get_frot(); + + std::string to_string() const; + std::string xml_str() const; + + private: + void set_filename(); + void read(const std::string& jinf_filename); + bool bool_value(char* line) const; + u_int16_t u_int16_value(char* line) const; + u_int32_t u_int32_value(char* line) const; + std::string& string_value(std::string& str, char* line) const; + char* find_value(char* line) const; + u_int32_t get_filesize(const std::string& file_name) const; + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_jinf_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jinf.hpp b/cpp/src/qpid/legacystore/jrnl/jinf.hpp deleted file mode 100644 index 0d3c9aa552..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/jinf.hpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file jinf.hpp - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::jinf class. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_jinf_hpp -#define mrg_journal_jinf_hpp - -#include -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - /** - * \class jinf - * \brief Class to handle the journal information file <basename>.jinf. - */ - class jinf - { - public: - typedef std::vector pfid_list; // pfids - typedef pfid_list::const_iterator pfidl_citr; - - private: - u_int8_t _jver; - std::string _jid; - std::string _jdir; - std::string _base_filename; - std::string _filename; - timespec _ts; - u_int16_t _num_jfiles; - bool _ae; - u_int32_t _ae_max_jfiles; - u_int32_t _jfsize_sblks; - u_int16_t _sblk_size_dblks; - u_int32_t _dblk_size; - u_int32_t _wcache_pgsize_sblks; - u_int16_t _wcache_num_pages; - u_int32_t _rcache_pgsize_sblks; - u_int16_t _rcache_num_pages; - std::tm* _tm_ptr; - bool _valid_flag; - bool _analyzed_flag; - pfid_list _pfid_list; - bool _initial_owi; - bool _frot; - - public: - // constructor for reading existing jinf file - jinf(const std::string& jinf_filename, bool validate_flag); - // constructor for writing jinf file - jinf(const std::string& jid, const std::string& jdir, const std::string& base_filename, - const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, const u_int32_t wcache_pgsize_sblks, const u_int16_t wcache_num_pages, - const timespec& ts); - virtual ~jinf(); - - void validate(); - void analyze(); - void write(); - - inline u_int8_t jver() const { return _jver; } - inline const std::string& jid() const { return _jid; } - inline const std::string& jdir() const { return _jdir; } - inline void set_jdir(const std::string& jdir) { _jdir = jdir; } - inline const std::string& base_filename() const { return _base_filename; } - inline const timespec& ts() const { return _ts; } - inline u_int16_t num_jfiles() const { return _num_jfiles; } - u_int16_t incr_num_jfiles(); - inline bool is_ae() const { return _ae; } - inline u_int16_t ae_max_jfiles() const { return _ae_max_jfiles; } - inline u_int32_t jfsize_sblks() const { return _jfsize_sblks; } - inline u_int16_t sblk_size_dblks() const { return _sblk_size_dblks; } - inline u_int32_t dblk_size() const { return _dblk_size; } - inline u_int32_t wcache_pgsize_sblks() const { return _wcache_pgsize_sblks; } - inline u_int16_t wcache_num_pages() const { return _wcache_num_pages; } - inline u_int32_t rcache_pgsize_sblks() const { return _rcache_pgsize_sblks; } - inline u_int16_t rcache_num_pages() const { return _rcache_num_pages; } - u_int16_t get_first_pfid(); - u_int16_t get_last_pfid(); - pfid_list& get_pfid_list(); - void get_normalized_pfid_list(pfid_list& pfid_list); - bool get_initial_owi(); - bool get_frot(); - - std::string to_string() const; - std::string xml_str() const; - - private: - void set_filename(); - void read(const std::string& jinf_filename); - bool bool_value(char* line) const; - u_int16_t u_int16_value(char* line) const; - u_int32_t u_int32_value(char* line) const; - std::string& string_value(std::string& str, char* line) const; - char* find_value(char* line) const; - u_int32_t get_filesize(const std::string& file_name) const; - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_jinf_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jrec.h b/cpp/src/qpid/legacystore/jrnl/jrec.h new file mode 100644 index 0000000000..abb77bbd2d --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/jrec.h @@ -0,0 +1,183 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file jrec.hpp + * + * Qpid asynchronous store plugin library + * + * File containing source code for class mrg::journal::jrec (abstract journal + * jrecord). See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_jrec_hpp +#define mrg_journal_jrec_hpp + +namespace mrg +{ +namespace journal +{ +class jrec; +} +} + +#include +#include +#include "jrnl/rec_hdr.hpp" +#include "jrnl/rec_tail.hpp" +#include +#include + +namespace mrg +{ +namespace journal +{ + + /** + * \class jrec + * \brief Abstract class for all file jrecords, both data and log. This class establishes + * the common data format and structure for these jrecords. + */ + class jrec + { + public: + jrec(); + virtual ~jrec(); + + /** + * \brief Encode this instance of jrec into the write buffer at the disk-block-aligned + * pointer wptr starting at position rec_offs_dblks in the encoded record to a + * maximum size of max_size_dblks. + * + * This call encodes the content of the data contianed in this instance of jrec into a + * disk-softblock-aligned (defined by JRNL_SBLK_SIZE) buffer pointed to by parameter + * wptr. No more than paramter max_size_dblks data-blocks may be written to the buffer. + * The parameter rec_offs_dblks is the offset in data-blocks within the fully encoded + * data block this instance represents at which to start encoding. + * + * Encoding entails writing the record header (struct enq_hdr), the data and the record tail + * (struct enq_tail). The record must be data-block-aligned (defined by JRNL_DBLK_SIZE), + * thus any remaining space in the final data-block is ignored; the returned value is the + * number of data-blocks consumed from the page by the encode action. Provided the initial + * alignment requirements are met, records may be of arbitrary size and may span multiple + * data-blocks, disk-blocks and/or pages. + * + * Since the record size in data-blocks is known, the general usage pattern is to call + * encode() as many times as is needed to fully encode the data. Each call to encode() + * will encode as much of the record as it can to what remains of the current page cache, + * and will return the number of data-blocks actually encoded. + * + * Example: Assume that record r1 was previously written to page 0, and that this + * is an instance representing record r2. Being larger than the page size ps, r2 would span + * multiple pages as follows: + *
+        *       |<---ps--->|
+        *       +----------+----------+----------+----...
+        *       |      |r2a|   r2b    |  r2c   | |
+        *       |<-r1-><----------r2---------->  |
+        *       +----------+----------+----------+----...
+        * page:      p0         p1         p2
+        * 
+ * Encoding record r2 will require multiple calls to encode; one for each page which + * is involved. Record r2 is divided logically into sections r2a, r2b and r2c at the + * points where the page boundaries intersect with the record. Assuming a page size + * of ps, the page boundary pointers are represented by their names p0, p1... and the + * sizes of the record segments are represented by their names r1, r2a, r2b..., the calls + * should be as follows: + *
+        * encode(p0+r1, 0, ps-r1); (returns r2a data-blocks)
+        * encode(p1, r2a, ps);     (returns r2b data-blocks which equals ps)
+        * encode(p2, r2a+r2b, ps); (returns r2c data-blocks)
+        * 
+ * + * \param wptr Data-block-aligned pointer to position in page buffer where encoding is to + * take place. + * \param rec_offs_dblks Offset in data-blocks within record from which to start encoding. + * \param max_size_dblks Maximum number of data-blocks to write to pointer wptr. + * \returns Number of data-blocks encoded. + */ + virtual u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, + u_int32_t max_size_dblks) = 0; + + /** + * \brief Decode into this instance of jrec from the read buffer at the disk-block-aligned + * pointer rptr starting at position jrec_offs_dblks in the encoded record to a + * maximum size of max_size_blks. + * + * This call decodes a record in the page buffer pointed to by the data-block-aligned + * (defined by JRNL_DBLK_SIZE) parameter rptr into this instance of jrec. No more than + * paramter max_size_dblks data-blocks may be read from the buffer. The parameter + * jrec_offs_dblks is the offset in data-blocks within the encoded record at which to start + * decoding. + * + * Decoding entails reading the record header, the data and the tail. The record is + * data-block-aligned (defined by JRNL_DBLK_SIZE); the returned value is the number of + * data-blocks read from the buffer by the decode action. As the record data size is only + * known once the header is read, the number of calls required to complete reading the + * record will depend on the vlaues within this instance which are set when the + * header is decoded. + * + * A non-zero value for jrec_offs_dblks implies that this is not the first call to + * decode and the record data will be appended at this offset. + * + * \param h Reference to instance of struct hdr, already read from page buffer and used + * to determine record type + * \param rptr Data-block-aligned pointer to position in page buffer where decoding is to + * begin. + * \param rec_offs_dblks Offset within record from which to start appending the decoded + * record. + * \param max_size_dblks Maximum number of data-blocks to read from pointer rptr. + * \returns Number of data-blocks read (consumed). + */ + virtual u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, + u_int32_t max_size_dblks) = 0; + + virtual bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs) = 0; + + virtual std::string& str(std::string& str) const = 0; + virtual std::size_t data_size() const = 0; + virtual std::size_t xid_size() const = 0; + virtual std::size_t rec_size() const = 0; + inline virtual u_int32_t rec_size_dblks() const { return size_dblks(rec_size()); } + static inline u_int32_t size_dblks(const std::size_t size) + { return size_blks(size, JRNL_DBLK_SIZE); } + static inline u_int32_t size_sblks(const std::size_t size) + { return size_blks(size, JRNL_DBLK_SIZE * JRNL_SBLK_SIZE); } + static inline u_int32_t size_blks(const std::size_t size, const std::size_t blksize) + { return (size + blksize - 1)/blksize; } + virtual u_int64_t rid() const = 0; + + protected: + virtual void chk_hdr() const = 0; + virtual void chk_hdr(u_int64_t rid) const = 0; + virtual void chk_tail() const = 0; + static void chk_hdr(const rec_hdr& hdr); + static void chk_rid(const rec_hdr& hdr, u_int64_t rid); + static void chk_tail(const rec_tail& tail, const rec_hdr& hdr); + virtual void clean() = 0; + }; // class jrec + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_jrec_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/jrec.hpp b/cpp/src/qpid/legacystore/jrnl/jrec.hpp deleted file mode 100644 index abb77bbd2d..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/jrec.hpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file jrec.hpp - * - * Qpid asynchronous store plugin library - * - * File containing source code for class mrg::journal::jrec (abstract journal - * jrecord). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_jrec_hpp -#define mrg_journal_jrec_hpp - -namespace mrg -{ -namespace journal -{ -class jrec; -} -} - -#include -#include -#include "jrnl/rec_hdr.hpp" -#include "jrnl/rec_tail.hpp" -#include -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class jrec - * \brief Abstract class for all file jrecords, both data and log. This class establishes - * the common data format and structure for these jrecords. - */ - class jrec - { - public: - jrec(); - virtual ~jrec(); - - /** - * \brief Encode this instance of jrec into the write buffer at the disk-block-aligned - * pointer wptr starting at position rec_offs_dblks in the encoded record to a - * maximum size of max_size_dblks. - * - * This call encodes the content of the data contianed in this instance of jrec into a - * disk-softblock-aligned (defined by JRNL_SBLK_SIZE) buffer pointed to by parameter - * wptr. No more than paramter max_size_dblks data-blocks may be written to the buffer. - * The parameter rec_offs_dblks is the offset in data-blocks within the fully encoded - * data block this instance represents at which to start encoding. - * - * Encoding entails writing the record header (struct enq_hdr), the data and the record tail - * (struct enq_tail). The record must be data-block-aligned (defined by JRNL_DBLK_SIZE), - * thus any remaining space in the final data-block is ignored; the returned value is the - * number of data-blocks consumed from the page by the encode action. Provided the initial - * alignment requirements are met, records may be of arbitrary size and may span multiple - * data-blocks, disk-blocks and/or pages. - * - * Since the record size in data-blocks is known, the general usage pattern is to call - * encode() as many times as is needed to fully encode the data. Each call to encode() - * will encode as much of the record as it can to what remains of the current page cache, - * and will return the number of data-blocks actually encoded. - * - * Example: Assume that record r1 was previously written to page 0, and that this - * is an instance representing record r2. Being larger than the page size ps, r2 would span - * multiple pages as follows: - *
-        *       |<---ps--->|
-        *       +----------+----------+----------+----...
-        *       |      |r2a|   r2b    |  r2c   | |
-        *       |<-r1-><----------r2---------->  |
-        *       +----------+----------+----------+----...
-        * page:      p0         p1         p2
-        * 
- * Encoding record r2 will require multiple calls to encode; one for each page which - * is involved. Record r2 is divided logically into sections r2a, r2b and r2c at the - * points where the page boundaries intersect with the record. Assuming a page size - * of ps, the page boundary pointers are represented by their names p0, p1... and the - * sizes of the record segments are represented by their names r1, r2a, r2b..., the calls - * should be as follows: - *
-        * encode(p0+r1, 0, ps-r1); (returns r2a data-blocks)
-        * encode(p1, r2a, ps);     (returns r2b data-blocks which equals ps)
-        * encode(p2, r2a+r2b, ps); (returns r2c data-blocks)
-        * 
- * - * \param wptr Data-block-aligned pointer to position in page buffer where encoding is to - * take place. - * \param rec_offs_dblks Offset in data-blocks within record from which to start encoding. - * \param max_size_dblks Maximum number of data-blocks to write to pointer wptr. - * \returns Number of data-blocks encoded. - */ - virtual u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks) = 0; - - /** - * \brief Decode into this instance of jrec from the read buffer at the disk-block-aligned - * pointer rptr starting at position jrec_offs_dblks in the encoded record to a - * maximum size of max_size_blks. - * - * This call decodes a record in the page buffer pointed to by the data-block-aligned - * (defined by JRNL_DBLK_SIZE) parameter rptr into this instance of jrec. No more than - * paramter max_size_dblks data-blocks may be read from the buffer. The parameter - * jrec_offs_dblks is the offset in data-blocks within the encoded record at which to start - * decoding. - * - * Decoding entails reading the record header, the data and the tail. The record is - * data-block-aligned (defined by JRNL_DBLK_SIZE); the returned value is the number of - * data-blocks read from the buffer by the decode action. As the record data size is only - * known once the header is read, the number of calls required to complete reading the - * record will depend on the vlaues within this instance which are set when the - * header is decoded. - * - * A non-zero value for jrec_offs_dblks implies that this is not the first call to - * decode and the record data will be appended at this offset. - * - * \param h Reference to instance of struct hdr, already read from page buffer and used - * to determine record type - * \param rptr Data-block-aligned pointer to position in page buffer where decoding is to - * begin. - * \param rec_offs_dblks Offset within record from which to start appending the decoded - * record. - * \param max_size_dblks Maximum number of data-blocks to read from pointer rptr. - * \returns Number of data-blocks read (consumed). - */ - virtual u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks) = 0; - - virtual bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs) = 0; - - virtual std::string& str(std::string& str) const = 0; - virtual std::size_t data_size() const = 0; - virtual std::size_t xid_size() const = 0; - virtual std::size_t rec_size() const = 0; - inline virtual u_int32_t rec_size_dblks() const { return size_dblks(rec_size()); } - static inline u_int32_t size_dblks(const std::size_t size) - { return size_blks(size, JRNL_DBLK_SIZE); } - static inline u_int32_t size_sblks(const std::size_t size) - { return size_blks(size, JRNL_DBLK_SIZE * JRNL_SBLK_SIZE); } - static inline u_int32_t size_blks(const std::size_t size, const std::size_t blksize) - { return (size + blksize - 1)/blksize; } - virtual u_int64_t rid() const = 0; - - protected: - virtual void chk_hdr() const = 0; - virtual void chk_hdr(u_int64_t rid) const = 0; - virtual void chk_tail() const = 0; - static void chk_hdr(const rec_hdr& hdr); - static void chk_rid(const rec_hdr& hdr, u_int64_t rid); - static void chk_tail(const rec_tail& tail, const rec_hdr& hdr); - virtual void clean() = 0; - }; // class jrec - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_jrec_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/lp_map.h b/cpp/src/qpid/legacystore/jrnl/lp_map.h new file mode 100644 index 0000000000..6ac39695d2 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/lp_map.h @@ -0,0 +1,83 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file lp_map.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::lp_map (logical file map). + * See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_lp_map_hpp +#define mrg_journal_lp_map_hpp + +#include +#include +#include +#include + +namespace mrg +{ +namespace journal +{ + /** + * \class lp_map + * \brief Maps the logical file id (lfid) to the physical file id (pfid) in the journal. + * + * NOTE: NOT THREAD SAFE + */ + class lp_map + { + public: + typedef std::map lp_map_t; + typedef lp_map_t::const_iterator lp_map_citr_t; + typedef lp_map_t::const_reverse_iterator lp_map_critr_t; + + private: + typedef std::pair lfpair; + typedef std::pair lfret; + lp_map_t _map; + + public: + lp_map(); + virtual ~lp_map(); + + void insert(u_int16_t lfid, u_int16_t pfid); + inline u_int16_t size() const { return u_int16_t(_map.size()); } + inline bool empty() const { return _map.empty(); } + inline lp_map_citr_t begin() { return _map.begin(); } + inline lp_map_citr_t end() { return _map.end(); } + inline lp_map_critr_t rbegin() { return _map.rbegin(); } + inline lp_map_critr_t rend() { return _map.rend(); } + void get_pfid_list(std::vector& pfid_list); + + // debug aid + std::string to_string(); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_lp_map_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/lp_map.hpp b/cpp/src/qpid/legacystore/jrnl/lp_map.hpp deleted file mode 100644 index 6ac39695d2..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/lp_map.hpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file lp_map.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::lp_map (logical file map). - * See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_lp_map_hpp -#define mrg_journal_lp_map_hpp - -#include -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - /** - * \class lp_map - * \brief Maps the logical file id (lfid) to the physical file id (pfid) in the journal. - * - * NOTE: NOT THREAD SAFE - */ - class lp_map - { - public: - typedef std::map lp_map_t; - typedef lp_map_t::const_iterator lp_map_citr_t; - typedef lp_map_t::const_reverse_iterator lp_map_critr_t; - - private: - typedef std::pair lfpair; - typedef std::pair lfret; - lp_map_t _map; - - public: - lp_map(); - virtual ~lp_map(); - - void insert(u_int16_t lfid, u_int16_t pfid); - inline u_int16_t size() const { return u_int16_t(_map.size()); } - inline bool empty() const { return _map.empty(); } - inline lp_map_citr_t begin() { return _map.begin(); } - inline lp_map_citr_t end() { return _map.end(); } - inline lp_map_critr_t rbegin() { return _map.rbegin(); } - inline lp_map_critr_t rend() { return _map.rend(); } - void get_pfid_list(std::vector& pfid_list); - - // debug aid - std::string to_string(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_lp_map_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/lpmgr.h b/cpp/src/qpid/legacystore/jrnl/lpmgr.h new file mode 100644 index 0000000000..3528db6f72 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/lpmgr.h @@ -0,0 +1,303 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file lpmgr.hpp + * + * Qpid asynchronous store plugin library + * + * Class mrg::journal::lpmgr. See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_lpmgr_hpp +#define mrg_journal_lpmgr_hpp + +namespace mrg +{ +namespace journal +{ + class jcntl; + class lpmgr; +} +} + +#include "jrnl/fcntl.hpp" +#include + +namespace mrg +{ +namespace journal +{ + + /** + * \brief LFID-PFID manager. This class maps the logical file id (lfid) to the physical file id (pfid) so that files + * may be inserted into the file ring buffer in (nearly) arbitrary logical locations while the physical ids continue + * to be appended. NOTE: NOT THREAD SAFE. + * + * The entire functionality of the LFID-PFID manager is to maintain an array of pointers to fcntl objects which have + * a one-to-one relationship to the physical %journal files. The logical file id (lfid) is used as an index to the + * array to read the mapped physical file id (pfid). By altering the order of these pointers within the array, the + * mapping of logical to physical files may be altered. This can be used to allow for the logical insertion of + * %journal files into a ring buffer, even though the physical file ids must be appended to those that preceded them. + * + * Since the insert() operation uses after-lfid as its position parameter, it is not possible to insert before lfid + * 0 - i.e. It is only possible to insert after an existing lfid. Consequently, lfid 0 and pfid 0 are always + * coincident in a %journal. Note, however, that inserting before lfid 0 is logically equivilent to inserting after + * the last lfid. + * + * When one or more files are inserted after a particular lfid, the lfids of the following files are incremented. The + * pfids of the inserted files follow those of all existing files, thus leading to a lfid-pfid discreppancy (ie no + * longer a one-to-one mapping): + * + * Example: Before insertion, %journal file headers would look as follows: + *
+    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
+    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
+    * pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
+    * lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
+    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
+    * 
+ * + * After insertion of 2 files after lid 2 (marked with *s): + *
+    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
+    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
+    * pfid --> | 0 | 1 | 2 |*6*|*7*| 3 | 4 | 5 |   pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |*6*|*7*|
+    * lfid --> | 0 | 1 | 2 |*3*|*4*| 5 | 6 | 7 |   lfid --> | 0 | 1 | 2 | 5 | 6 | 7 |*3*|*4*|
+    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
+    * 
+ * + * The insert() function updates the internal map immediately, but the physical files (which have both the pfid and + * lfid written into the file header) are only updated as they are overwritten in the normal course of enqueueing + * and dequeueing messages. If the %journal should fail after insertion but before the files following those inserted + * are overwritten, then duplicate lfids will be present (though no duplicate pfids are possible). The overwrite + * indicator (owi) flag and the pfid numbers may be used to resolve the ambiguity and determine the logically earlier + * lfid in this case. + * + * Example: Before insertion, the current active write file being lfid/pfid 2 as determined by the owi flag, %journal + * file headers would look as follows: + *
+    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
+    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
+    * pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
+    * lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
+    *  owi --> | t | t | t | f | f | f |            owi --> | t | t | t | f | f | f |
+    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
+    * 
+ * + * After inserting 2 files after lfid 2 and then 3 (the newly inserted file) - marked with *s: + *
+    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
+    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
+    * pfid --> | 0 | 1 | 2 |*6*|*7*| 3 | 4 | 5 |   pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |*3*|*4*|
+    * lfid --> | 0 | 1 | 2 |*3*|*4*| 3 | 4 | 5 |   lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |*3*|*4*|
+    *  owi --> | t | t | t | t | t | f | f | f |    owi --> | t | t | t | f | f | f | t | t |
+    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
+    * 
+ * + * If a broker failure occurs at this point, then there are two independent tests that may be made to resolve + * duplicate lfids during recovery in such cases: + *
    + *
  1. The correct lfid has owi flag that matches that of pfid/lfid 0
  2. + *
  3. The most recently inserted (hence correct) lfid has pfids that are higher than the duplicate that was not + * overwritten
  4. + *
+ * + * NOTE: NOT THREAD SAFE. Provide external thread protection if used in multi-threaded environments. + */ + class lpmgr + { + public: + /** + * \brief Function pointer to function that will create a new fcntl object and return its pointer. + * + * \param jcp Pointer to jcntl instance from which journal file details will be obtained. + * \param lfid Logical file ID for new fcntl instance. + * \param pfid Physical file ID for file associated with new fcntl instance. + * \param rdp Pointer to rcvdat instance which conatins recovery information for new fcntl instance when + * recovering an existing file, or null if a new file is to be created. + */ + typedef fcntl* (new_obj_fn_ptr)(jcntl* const jcp, + const u_int16_t lfid, + const u_int16_t pfid, + const rcvdat* const rdp); + + private: + bool _ae; ///< Auto-expand mode + u_int16_t _ae_max_jfiles; ///< Max file count for auto-expansion; 0 = no limit + std::vector _fcntl_arr; ///< Array of pointers to fcntl objects + + public: + lpmgr(); + virtual ~lpmgr(); + + /** + * \brief Initialize from scratch for a known number of %journal files. All lfid values are identical to pfid + * values (which is normal before any inserts have occurred). + * + * \param num_jfiles Number of files to be created, and consequently the number of fcntl objects in array + * _fcntl_arr. + * \param ae If true, allows auto-expansion; if false, disables auto-expansion. + * \param ae_max_jfiles The maximum number of files allowed for auto-expansion. Cannot be lower than the current + * number of files. However, a zero value disables the limit checks, and allows unlimited + * expansion. + * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that + * new files may be created. + * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence + * causes a new %journal file to be created). + */ + void initialize(const u_int16_t num_jfiles, + const bool ae, + const u_int16_t ae_max_jfiles, + jcntl* const jcp, + new_obj_fn_ptr fp); + + /** + * \brief Initialize from a known lfid-pfid map pfid_list (within rcvdat param rd), which is usually obtained + * from a recover. The index of pfid_list is the logical file id (lfid); the value contained in the vector is + * the physical file id (pfid). + * + * \param rd Ref to rcvdat struct which contains recovery data and the pfid_list. + * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that + * new files may be created. + * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence + * causes a new %journal file to be created). + */ + void recover(const rcvdat& rd, + jcntl* const jcp, + new_obj_fn_ptr fp); + + /** + * \brief Insert num_jfiles files after lfid index after_lfid. This causes all lfids after after_lfid to be + * increased by num_jfiles. + * + * Note that it is not possible to insert before lfid 0, and thus lfid 0 should always point to pfid 0. + * Inserting before lfid 0 is logically equivilent to inserting after the last lfid in a circular buffer. + * + * \param after_lfid Lid index after which to insert file(s). + * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that + * new files may be created. + * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence + * causes a new %journal file to be created). + * \param num_jfiles The number of files by which to increase. + */ + void insert(const u_int16_t after_lfid, + jcntl* const jcp, + new_obj_fn_ptr fp, + const u_int16_t num_jfiles = 1); + + /** + * \brief Clears _fcntl_arr and deletes all fcntl instances. + */ + void finalize(); + + /** + * \brief Returns true if initialized; false otherwise. After construction, will return false until initialize() + * is called; thereafter true until finalize() is called, whereupon it will return false again. + * + * \return True if initialized; false otherwise. + */ + inline bool is_init() const { return _fcntl_arr.size() > 0; } + + /** + * \brief Returns true if auto-expand mode is enabled; false if not. + * + * \return True if auto-expand mode is enabled; false if not. + */ + inline bool is_ae() const { return _ae; } + + /** + * \brief Sets the auto-expand mode to enabled if ae is true, to disabled otherwise. The value of _ae_max_jfiles + * must be valid to succeed (i.e. _ae_max_jfiles must be greater than the current number of files or be zero). + * + * \param ae If true will enable auto-expand mode; if false will disable it. + */ + void set_ae(const bool ae); + + /** + * \brief Returns the number of %journal files, including any that were appended or inserted since + * initialization. + * + * \return Number of %journal files if initialized; 0 otherwise. + */ + inline u_int16_t num_jfiles() const { return static_cast(_fcntl_arr.size()); } + + /** + * \brief Returns the maximum number of files allowed for auto-expansion. + * + * \return Maximum number of files allowed for auto-expansion. A zero value represents a disabled limit + * - i.e. unlimited expansion. + */ + inline u_int16_t ae_max_jfiles() const { return _ae_max_jfiles; } + + /** + * \brief Sets the maximum number of files allowed for auto-expansion. A zero value disables the limit. + * + * \param ae_max_jfiles The maximum number of files allowed for auto-expansion. Cannot be lower than the current + * number of files. However, a zero value disables the limit checks, and allows unlimited + * expansion. + */ + void set_ae_max_jfiles(const u_int16_t ae_max_jfiles); + + /** + * \brief Calculates the number of future files available for auto-expansion. + * + * \return The number of future files available for auto-expansion. + */ + u_int16_t ae_jfiles_rem() const; + + /** + * \brief Get a pointer to fcntl instance for a given lfid. + * + * \return Pointer to fcntl object corresponding to logical file id lfid, or 0 if lfid is out of range + * (greater than number of files in use). + */ + inline fcntl* get_fcntlp(const u_int16_t lfid) const + { if (lfid >= _fcntl_arr.size()) return 0; return _fcntl_arr[lfid]; } + + // Testing functions + void get_pfid_list(std::vector& pfid_list) const; + void get_lfid_list(std::vector& lfid_list) const; + + protected: + + /** + * \brief Append num_jfiles files to the end of the logical and file id sequence. This is similar to extending + * the from-scratch initialization. + * + * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that + * new files may be created. + * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence + * causes a new %journal file to be created). + * \param num_jfiles The number of files by which to increase. + */ + void append(jcntl* const jcp, + new_obj_fn_ptr fp, + const u_int16_t num_jfiles = 1); + + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_lpmgr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/lpmgr.hpp b/cpp/src/qpid/legacystore/jrnl/lpmgr.hpp deleted file mode 100644 index 3528db6f72..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/lpmgr.hpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file lpmgr.hpp - * - * Qpid asynchronous store plugin library - * - * Class mrg::journal::lpmgr. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_lpmgr_hpp -#define mrg_journal_lpmgr_hpp - -namespace mrg -{ -namespace journal -{ - class jcntl; - class lpmgr; -} -} - -#include "jrnl/fcntl.hpp" -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \brief LFID-PFID manager. This class maps the logical file id (lfid) to the physical file id (pfid) so that files - * may be inserted into the file ring buffer in (nearly) arbitrary logical locations while the physical ids continue - * to be appended. NOTE: NOT THREAD SAFE. - * - * The entire functionality of the LFID-PFID manager is to maintain an array of pointers to fcntl objects which have - * a one-to-one relationship to the physical %journal files. The logical file id (lfid) is used as an index to the - * array to read the mapped physical file id (pfid). By altering the order of these pointers within the array, the - * mapping of logical to physical files may be altered. This can be used to allow for the logical insertion of - * %journal files into a ring buffer, even though the physical file ids must be appended to those that preceded them. - * - * Since the insert() operation uses after-lfid as its position parameter, it is not possible to insert before lfid - * 0 - i.e. It is only possible to insert after an existing lfid. Consequently, lfid 0 and pfid 0 are always - * coincident in a %journal. Note, however, that inserting before lfid 0 is logically equivilent to inserting after - * the last lfid. - * - * When one or more files are inserted after a particular lfid, the lfids of the following files are incremented. The - * pfids of the inserted files follow those of all existing files, thus leading to a lfid-pfid discreppancy (ie no - * longer a one-to-one mapping): - * - * Example: Before insertion, %journal file headers would look as follows: - *
-    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
-    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
-    * pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
-    * lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
-    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
-    * 
- * - * After insertion of 2 files after lid 2 (marked with *s): - *
-    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
-    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
-    * pfid --> | 0 | 1 | 2 |*6*|*7*| 3 | 4 | 5 |   pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |*6*|*7*|
-    * lfid --> | 0 | 1 | 2 |*3*|*4*| 5 | 6 | 7 |   lfid --> | 0 | 1 | 2 | 5 | 6 | 7 |*3*|*4*|
-    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
-    * 
- * - * The insert() function updates the internal map immediately, but the physical files (which have both the pfid and - * lfid written into the file header) are only updated as they are overwritten in the normal course of enqueueing - * and dequeueing messages. If the %journal should fail after insertion but before the files following those inserted - * are overwritten, then duplicate lfids will be present (though no duplicate pfids are possible). The overwrite - * indicator (owi) flag and the pfid numbers may be used to resolve the ambiguity and determine the logically earlier - * lfid in this case. - * - * Example: Before insertion, the current active write file being lfid/pfid 2 as determined by the owi flag, %journal - * file headers would look as follows: - *
-    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
-    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
-    * pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
-    * lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
-    *  owi --> | t | t | t | f | f | f |            owi --> | t | t | t | f | f | f |
-    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
-    * 
- * - * After inserting 2 files after lfid 2 and then 3 (the newly inserted file) - marked with *s: - *
-    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
-    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
-    * pfid --> | 0 | 1 | 2 |*6*|*7*| 3 | 4 | 5 |   pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |*3*|*4*|
-    * lfid --> | 0 | 1 | 2 |*3*|*4*| 3 | 4 | 5 |   lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |*3*|*4*|
-    *  owi --> | t | t | t | t | t | f | f | f |    owi --> | t | t | t | f | f | f | t | t |
-    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
-    * 
- * - * If a broker failure occurs at this point, then there are two independent tests that may be made to resolve - * duplicate lfids during recovery in such cases: - *
    - *
  1. The correct lfid has owi flag that matches that of pfid/lfid 0
  2. - *
  3. The most recently inserted (hence correct) lfid has pfids that are higher than the duplicate that was not - * overwritten
  4. - *
- * - * NOTE: NOT THREAD SAFE. Provide external thread protection if used in multi-threaded environments. - */ - class lpmgr - { - public: - /** - * \brief Function pointer to function that will create a new fcntl object and return its pointer. - * - * \param jcp Pointer to jcntl instance from which journal file details will be obtained. - * \param lfid Logical file ID for new fcntl instance. - * \param pfid Physical file ID for file associated with new fcntl instance. - * \param rdp Pointer to rcvdat instance which conatins recovery information for new fcntl instance when - * recovering an existing file, or null if a new file is to be created. - */ - typedef fcntl* (new_obj_fn_ptr)(jcntl* const jcp, - const u_int16_t lfid, - const u_int16_t pfid, - const rcvdat* const rdp); - - private: - bool _ae; ///< Auto-expand mode - u_int16_t _ae_max_jfiles; ///< Max file count for auto-expansion; 0 = no limit - std::vector _fcntl_arr; ///< Array of pointers to fcntl objects - - public: - lpmgr(); - virtual ~lpmgr(); - - /** - * \brief Initialize from scratch for a known number of %journal files. All lfid values are identical to pfid - * values (which is normal before any inserts have occurred). - * - * \param num_jfiles Number of files to be created, and consequently the number of fcntl objects in array - * _fcntl_arr. - * \param ae If true, allows auto-expansion; if false, disables auto-expansion. - * \param ae_max_jfiles The maximum number of files allowed for auto-expansion. Cannot be lower than the current - * number of files. However, a zero value disables the limit checks, and allows unlimited - * expansion. - * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that - * new files may be created. - * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence - * causes a new %journal file to be created). - */ - void initialize(const u_int16_t num_jfiles, - const bool ae, - const u_int16_t ae_max_jfiles, - jcntl* const jcp, - new_obj_fn_ptr fp); - - /** - * \brief Initialize from a known lfid-pfid map pfid_list (within rcvdat param rd), which is usually obtained - * from a recover. The index of pfid_list is the logical file id (lfid); the value contained in the vector is - * the physical file id (pfid). - * - * \param rd Ref to rcvdat struct which contains recovery data and the pfid_list. - * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that - * new files may be created. - * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence - * causes a new %journal file to be created). - */ - void recover(const rcvdat& rd, - jcntl* const jcp, - new_obj_fn_ptr fp); - - /** - * \brief Insert num_jfiles files after lfid index after_lfid. This causes all lfids after after_lfid to be - * increased by num_jfiles. - * - * Note that it is not possible to insert before lfid 0, and thus lfid 0 should always point to pfid 0. - * Inserting before lfid 0 is logically equivilent to inserting after the last lfid in a circular buffer. - * - * \param after_lfid Lid index after which to insert file(s). - * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that - * new files may be created. - * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence - * causes a new %journal file to be created). - * \param num_jfiles The number of files by which to increase. - */ - void insert(const u_int16_t after_lfid, - jcntl* const jcp, - new_obj_fn_ptr fp, - const u_int16_t num_jfiles = 1); - - /** - * \brief Clears _fcntl_arr and deletes all fcntl instances. - */ - void finalize(); - - /** - * \brief Returns true if initialized; false otherwise. After construction, will return false until initialize() - * is called; thereafter true until finalize() is called, whereupon it will return false again. - * - * \return True if initialized; false otherwise. - */ - inline bool is_init() const { return _fcntl_arr.size() > 0; } - - /** - * \brief Returns true if auto-expand mode is enabled; false if not. - * - * \return True if auto-expand mode is enabled; false if not. - */ - inline bool is_ae() const { return _ae; } - - /** - * \brief Sets the auto-expand mode to enabled if ae is true, to disabled otherwise. The value of _ae_max_jfiles - * must be valid to succeed (i.e. _ae_max_jfiles must be greater than the current number of files or be zero). - * - * \param ae If true will enable auto-expand mode; if false will disable it. - */ - void set_ae(const bool ae); - - /** - * \brief Returns the number of %journal files, including any that were appended or inserted since - * initialization. - * - * \return Number of %journal files if initialized; 0 otherwise. - */ - inline u_int16_t num_jfiles() const { return static_cast(_fcntl_arr.size()); } - - /** - * \brief Returns the maximum number of files allowed for auto-expansion. - * - * \return Maximum number of files allowed for auto-expansion. A zero value represents a disabled limit - * - i.e. unlimited expansion. - */ - inline u_int16_t ae_max_jfiles() const { return _ae_max_jfiles; } - - /** - * \brief Sets the maximum number of files allowed for auto-expansion. A zero value disables the limit. - * - * \param ae_max_jfiles The maximum number of files allowed for auto-expansion. Cannot be lower than the current - * number of files. However, a zero value disables the limit checks, and allows unlimited - * expansion. - */ - void set_ae_max_jfiles(const u_int16_t ae_max_jfiles); - - /** - * \brief Calculates the number of future files available for auto-expansion. - * - * \return The number of future files available for auto-expansion. - */ - u_int16_t ae_jfiles_rem() const; - - /** - * \brief Get a pointer to fcntl instance for a given lfid. - * - * \return Pointer to fcntl object corresponding to logical file id lfid, or 0 if lfid is out of range - * (greater than number of files in use). - */ - inline fcntl* get_fcntlp(const u_int16_t lfid) const - { if (lfid >= _fcntl_arr.size()) return 0; return _fcntl_arr[lfid]; } - - // Testing functions - void get_pfid_list(std::vector& pfid_list) const; - void get_lfid_list(std::vector& lfid_list) const; - - protected: - - /** - * \brief Append num_jfiles files to the end of the logical and file id sequence. This is similar to extending - * the from-scratch initialization. - * - * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that - * new files may be created. - * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence - * causes a new %journal file to be created). - * \param num_jfiles The number of files by which to increase. - */ - void append(jcntl* const jcp, - new_obj_fn_ptr fp, - const u_int16_t num_jfiles = 1); - - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_lpmgr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/pmgr.h b/cpp/src/qpid/legacystore/jrnl/pmgr.h new file mode 100644 index 0000000000..3ce8851d70 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/pmgr.h @@ -0,0 +1,142 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file pmgr.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::pmgr (page manager). See + * class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_pmgr_hpp +#define mrg_journal_pmgr_hpp + +namespace mrg +{ +namespace journal +{ + class pmgr; + class jcntl; +} +} + +#include +#include "jrnl/aio.hpp" +#include "jrnl/aio_callback.hpp" +#include "jrnl/data_tok.hpp" +#include "jrnl/deq_rec.hpp" +#include "jrnl/enq_map.hpp" +#include "jrnl/enq_rec.hpp" +#include "jrnl/fcntl.hpp" +#include "jrnl/txn_map.hpp" +#include "jrnl/txn_rec.hpp" + +namespace mrg +{ +namespace journal +{ + + /** + * \brief Abstract class for managing either read or write page cache of arbitrary size and + * number of cache_num_pages. + */ + class pmgr + { + public: + /** + * \brief Enumeration of possible stats of a page within a page cache. + */ + enum page_state + { + UNUSED, ///< A page is uninitialized, contains no data. + IN_USE, ///< Page is in use. + AIO_PENDING, ///< An AIO request outstanding. + AIO_COMPLETE ///< An AIO request is complete. + }; + + protected: + /** + * \brief Page control block, carries control and state information for each page in the + * cache. + */ + struct page_cb + { + u_int16_t _index; ///< Index of this page + page_state _state; ///< Status of page + u_int64_t _frid; ///< First rid in page (used for fhdr init) + u_int32_t _wdblks; ///< Total number of dblks in page so far + u_int32_t _rdblks; ///< Total number of dblks in page + std::deque* _pdtokl; ///< Page message tokens list + fcntl* _wfh; ///< File handle for incrementing write compl counts + fcntl* _rfh; ///< File handle for incrementing read compl counts + void* _pbuff; ///< Page buffer + + page_cb(u_int16_t index); ///< Convenience constructor + const char* state_str() const; ///< Return state as string for this pcb + }; + + static const u_int32_t _sblksize; ///< Disk softblock size + u_int32_t _cache_pgsize_sblks; ///< Size of page cache cache_num_pages + u_int16_t _cache_num_pages; ///< Number of page cache cache_num_pages + jcntl* _jc; ///< Pointer to journal controller + enq_map& _emap; ///< Ref to enqueue map + txn_map& _tmap; ///< Ref to transaction map + void* _page_base_ptr; ///< Base pointer to page memory + void** _page_ptr_arr; ///< Array of pointers to cache_num_pages in page memory + page_cb* _page_cb_arr; ///< Array of page_cb structs + aio_cb* _aio_cb_arr; ///< Array of iocb structs + aio_event* _aio_event_arr; ///< Array of io_events + io_context_t _ioctx; ///< AIO context for read/write operations + u_int16_t _pg_index; ///< Index of current page being used + u_int32_t _pg_cntr; ///< Page counter; determines if file rotation req'd + u_int32_t _pg_offset_dblks; ///< Page offset (used so far) in data blocks + u_int32_t _aio_evt_rem; ///< Remaining AIO events + aio_callback* _cbp; ///< Pointer to callback object + + enq_rec _enq_rec; ///< Enqueue record used for encoding/decoding + deq_rec _deq_rec; ///< Dequeue record used for encoding/decoding + txn_rec _txn_rec; ///< Transaction record used for encoding/decoding + + public: + pmgr(jcntl* jc, enq_map& emap, txn_map& tmap); + virtual ~pmgr(); + + virtual int32_t get_events(page_state state, timespec* const timeout, bool flush = false) = 0; + inline u_int32_t get_aio_evt_rem() const { return _aio_evt_rem; } + static const char* page_state_str(page_state ps); + inline u_int32_t cache_pgsize_sblks() const { return _cache_pgsize_sblks; } + inline u_int16_t cache_num_pages() const { return _cache_num_pages; } + + protected: + virtual void initialize(aio_callback* const cbp, const u_int32_t cache_pgsize_sblks, + const u_int16_t cache_num_pages); + virtual void rotate_page() = 0; + virtual void clean(); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_pmgr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/pmgr.hpp b/cpp/src/qpid/legacystore/jrnl/pmgr.hpp deleted file mode 100644 index 3ce8851d70..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/pmgr.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file pmgr.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::pmgr (page manager). See - * class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_pmgr_hpp -#define mrg_journal_pmgr_hpp - -namespace mrg -{ -namespace journal -{ - class pmgr; - class jcntl; -} -} - -#include -#include "jrnl/aio.hpp" -#include "jrnl/aio_callback.hpp" -#include "jrnl/data_tok.hpp" -#include "jrnl/deq_rec.hpp" -#include "jrnl/enq_map.hpp" -#include "jrnl/enq_rec.hpp" -#include "jrnl/fcntl.hpp" -#include "jrnl/txn_map.hpp" -#include "jrnl/txn_rec.hpp" - -namespace mrg -{ -namespace journal -{ - - /** - * \brief Abstract class for managing either read or write page cache of arbitrary size and - * number of cache_num_pages. - */ - class pmgr - { - public: - /** - * \brief Enumeration of possible stats of a page within a page cache. - */ - enum page_state - { - UNUSED, ///< A page is uninitialized, contains no data. - IN_USE, ///< Page is in use. - AIO_PENDING, ///< An AIO request outstanding. - AIO_COMPLETE ///< An AIO request is complete. - }; - - protected: - /** - * \brief Page control block, carries control and state information for each page in the - * cache. - */ - struct page_cb - { - u_int16_t _index; ///< Index of this page - page_state _state; ///< Status of page - u_int64_t _frid; ///< First rid in page (used for fhdr init) - u_int32_t _wdblks; ///< Total number of dblks in page so far - u_int32_t _rdblks; ///< Total number of dblks in page - std::deque* _pdtokl; ///< Page message tokens list - fcntl* _wfh; ///< File handle for incrementing write compl counts - fcntl* _rfh; ///< File handle for incrementing read compl counts - void* _pbuff; ///< Page buffer - - page_cb(u_int16_t index); ///< Convenience constructor - const char* state_str() const; ///< Return state as string for this pcb - }; - - static const u_int32_t _sblksize; ///< Disk softblock size - u_int32_t _cache_pgsize_sblks; ///< Size of page cache cache_num_pages - u_int16_t _cache_num_pages; ///< Number of page cache cache_num_pages - jcntl* _jc; ///< Pointer to journal controller - enq_map& _emap; ///< Ref to enqueue map - txn_map& _tmap; ///< Ref to transaction map - void* _page_base_ptr; ///< Base pointer to page memory - void** _page_ptr_arr; ///< Array of pointers to cache_num_pages in page memory - page_cb* _page_cb_arr; ///< Array of page_cb structs - aio_cb* _aio_cb_arr; ///< Array of iocb structs - aio_event* _aio_event_arr; ///< Array of io_events - io_context_t _ioctx; ///< AIO context for read/write operations - u_int16_t _pg_index; ///< Index of current page being used - u_int32_t _pg_cntr; ///< Page counter; determines if file rotation req'd - u_int32_t _pg_offset_dblks; ///< Page offset (used so far) in data blocks - u_int32_t _aio_evt_rem; ///< Remaining AIO events - aio_callback* _cbp; ///< Pointer to callback object - - enq_rec _enq_rec; ///< Enqueue record used for encoding/decoding - deq_rec _deq_rec; ///< Dequeue record used for encoding/decoding - txn_rec _txn_rec; ///< Transaction record used for encoding/decoding - - public: - pmgr(jcntl* jc, enq_map& emap, txn_map& tmap); - virtual ~pmgr(); - - virtual int32_t get_events(page_state state, timespec* const timeout, bool flush = false) = 0; - inline u_int32_t get_aio_evt_rem() const { return _aio_evt_rem; } - static const char* page_state_str(page_state ps); - inline u_int32_t cache_pgsize_sblks() const { return _cache_pgsize_sblks; } - inline u_int16_t cache_num_pages() const { return _cache_num_pages; } - - protected: - virtual void initialize(aio_callback* const cbp, const u_int32_t cache_pgsize_sblks, - const u_int16_t cache_num_pages); - virtual void rotate_page() = 0; - virtual void clean(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_pmgr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rcvdat.h b/cpp/src/qpid/legacystore/jrnl/rcvdat.h new file mode 100644 index 0000000000..90f5a5ad58 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/rcvdat.h @@ -0,0 +1,181 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file rcvdat.hpp + * + * Qpid asynchronous store plugin library + * + * Contains structure for recovery status and offset data. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_rcvdat_hpp +#define mrg_journal_rcvdat_hpp + +#include +#include +#include +#include "jrnl/jcfg.hpp" +#include +#include +#include + +namespace mrg +{ +namespace journal +{ + + struct rcvdat + { + u_int16_t _njf; ///< Number of journal files + bool _ae; ///< Auto-expand mode + u_int16_t _aemjf; ///< Auto-expand mode max journal files + bool _owi; ///< Overwrite indicator + bool _frot; ///< First rotation flag + bool _jempty; ///< Journal data files empty + u_int16_t _ffid; ///< First file id + std::size_t _fro; ///< First record offset in ffid + u_int16_t _lfid; ///< Last file id + std::size_t _eo; ///< End offset (first byte past last record) + u_int64_t _h_rid; ///< Highest rid found + bool _lffull; ///< Last file is full + bool _jfull; ///< Journal is full + std::vector _fid_list; ///< Fid-lid mapping - list of fids in order of lid + std::vector _enq_cnt_list; ///< Number enqueued records found for each file + + rcvdat(): + _njf(0), + _ae(false), + _aemjf(0), + _owi(false), + _frot(false), + _jempty(true), + _ffid(0), + _fro(0), + _lfid(0), + _eo(0), + _h_rid(0), + _lffull(false), + _jfull(false), + _fid_list(), + _enq_cnt_list() + {} + + void reset(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles) + { + _njf = num_jfiles; + _ae = auto_expand; + _aemjf = ae_max_jfiles; + _owi = false; + _frot = false; + _jempty = true; + _ffid = 0; + _fro = 0; + _lfid = 0; + _eo = 0; + _h_rid = 0; + _lffull = false; + _jfull = false; + _fid_list.clear(); + _enq_cnt_list.clear(); + _enq_cnt_list.resize(num_jfiles, 0); + } + + // Find first fid with enqueued records + u_int16_t ffid() + { + u_int16_t index = _ffid; + while (index != _lfid && _enq_cnt_list[index] == 0) + { + if (++index >= _njf) + index = 0; + } + return index; + } + + std::string to_string(const std::string& jid) + { + std::ostringstream oss; + oss << "Recover file analysis (jid=\"" << jid << "\"):" << std::endl; + oss << " Number of journal files (_njf) = " << _njf << std::endl; + oss << " Auto-expand mode (_ae) = " << (_ae ? "TRUE" : "FALSE") << std::endl; + if (_ae) oss << " Auto-expand mode max journal files (_aemjf) = " << _aemjf << std::endl; + oss << " Overwrite indicator (_owi) = " << (_owi ? "TRUE" : "FALSE") << std::endl; + oss << " First rotation (_frot) = " << (_frot ? "TRUE" : "FALSE") << std::endl; + oss << " Journal empty (_jempty) = " << (_jempty ? "TRUE" : "FALSE") << std::endl; + oss << " First (earliest) fid (_ffid) = " << _ffid << std::endl; + oss << " First record offset in first fid (_fro) = 0x" << std::hex << _fro << + std::dec << " (" << (_fro/JRNL_DBLK_SIZE) << " dblks)" << std::endl; + oss << " Last (most recent) fid (_lfid) = " << _lfid << std::endl; + oss << " End offset (_eo) = 0x" << std::hex << _eo << std::dec << " (" << + (_eo/JRNL_DBLK_SIZE) << " dblks)" << std::endl; + oss << " Highest rid (_h_rid) = 0x" << std::hex << _h_rid << std::dec << std::endl; + oss << " Last file full (_lffull) = " << (_lffull ? "TRUE" : "FALSE") << std::endl; + oss << " Journal full (_jfull) = " << (_jfull ? "TRUE" : "FALSE") << std::endl; + oss << " Normalized fid list (_fid_list) = ["; + for (std::vector::const_iterator i = _fid_list.begin(); i < _fid_list.end(); i++) + { + if (i != _fid_list.begin()) oss << ", "; + oss << *i; + } + oss << "]" << std::endl; + oss << " Enqueued records (txn & non-txn):" << std::endl; + for (unsigned i=0; i<_enq_cnt_list.size(); i++) + oss << " File " << std::setw(2) << i << ": " << _enq_cnt_list[i] << + std::endl; + return oss.str(); + } + + std::string to_log(const std::string& jid) + { + std::ostringstream oss; + oss << "Recover file analysis (jid=\"" << jid << "\"):"; + oss << " njf=" << _njf; + oss << " ae=" << (_owi ? "T" : "F"); + oss << " aemjf=" << _aemjf; + oss << " owi=" << (_ae ? "T" : "F"); + oss << " frot=" << (_frot ? "T" : "F"); + oss << " jempty=" << (_jempty ? "T" : "F"); + oss << " ffid=" << _ffid; + oss << " fro=0x" << std::hex << _fro << std::dec << " (" << + (_fro/JRNL_DBLK_SIZE) << " dblks)"; + oss << " lfid=" << _lfid; + oss << " eo=0x" << std::hex << _eo << std::dec << " (" << + (_eo/JRNL_DBLK_SIZE) << " dblks)"; + oss << " h_rid=0x" << std::hex << _h_rid << std::dec; + oss << " lffull=" << (_lffull ? "T" : "F"); + oss << " jfull=" << (_jfull ? "T" : "F"); + oss << " Enqueued records (txn & non-txn): [ "; + for (unsigned i=0; i<_enq_cnt_list.size(); i++) + { + if (i) oss << " "; + oss << "fid_" << std::setw(2) << std::setfill('0') << i << "=" << _enq_cnt_list[i]; + } + oss << " ]"; + return oss.str(); + } + }; +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_rcvdat_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rcvdat.hpp b/cpp/src/qpid/legacystore/jrnl/rcvdat.hpp deleted file mode 100644 index 90f5a5ad58..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/rcvdat.hpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file rcvdat.hpp - * - * Qpid asynchronous store plugin library - * - * Contains structure for recovery status and offset data. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_rcvdat_hpp -#define mrg_journal_rcvdat_hpp - -#include -#include -#include -#include "jrnl/jcfg.hpp" -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - - struct rcvdat - { - u_int16_t _njf; ///< Number of journal files - bool _ae; ///< Auto-expand mode - u_int16_t _aemjf; ///< Auto-expand mode max journal files - bool _owi; ///< Overwrite indicator - bool _frot; ///< First rotation flag - bool _jempty; ///< Journal data files empty - u_int16_t _ffid; ///< First file id - std::size_t _fro; ///< First record offset in ffid - u_int16_t _lfid; ///< Last file id - std::size_t _eo; ///< End offset (first byte past last record) - u_int64_t _h_rid; ///< Highest rid found - bool _lffull; ///< Last file is full - bool _jfull; ///< Journal is full - std::vector _fid_list; ///< Fid-lid mapping - list of fids in order of lid - std::vector _enq_cnt_list; ///< Number enqueued records found for each file - - rcvdat(): - _njf(0), - _ae(false), - _aemjf(0), - _owi(false), - _frot(false), - _jempty(true), - _ffid(0), - _fro(0), - _lfid(0), - _eo(0), - _h_rid(0), - _lffull(false), - _jfull(false), - _fid_list(), - _enq_cnt_list() - {} - - void reset(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles) - { - _njf = num_jfiles; - _ae = auto_expand; - _aemjf = ae_max_jfiles; - _owi = false; - _frot = false; - _jempty = true; - _ffid = 0; - _fro = 0; - _lfid = 0; - _eo = 0; - _h_rid = 0; - _lffull = false; - _jfull = false; - _fid_list.clear(); - _enq_cnt_list.clear(); - _enq_cnt_list.resize(num_jfiles, 0); - } - - // Find first fid with enqueued records - u_int16_t ffid() - { - u_int16_t index = _ffid; - while (index != _lfid && _enq_cnt_list[index] == 0) - { - if (++index >= _njf) - index = 0; - } - return index; - } - - std::string to_string(const std::string& jid) - { - std::ostringstream oss; - oss << "Recover file analysis (jid=\"" << jid << "\"):" << std::endl; - oss << " Number of journal files (_njf) = " << _njf << std::endl; - oss << " Auto-expand mode (_ae) = " << (_ae ? "TRUE" : "FALSE") << std::endl; - if (_ae) oss << " Auto-expand mode max journal files (_aemjf) = " << _aemjf << std::endl; - oss << " Overwrite indicator (_owi) = " << (_owi ? "TRUE" : "FALSE") << std::endl; - oss << " First rotation (_frot) = " << (_frot ? "TRUE" : "FALSE") << std::endl; - oss << " Journal empty (_jempty) = " << (_jempty ? "TRUE" : "FALSE") << std::endl; - oss << " First (earliest) fid (_ffid) = " << _ffid << std::endl; - oss << " First record offset in first fid (_fro) = 0x" << std::hex << _fro << - std::dec << " (" << (_fro/JRNL_DBLK_SIZE) << " dblks)" << std::endl; - oss << " Last (most recent) fid (_lfid) = " << _lfid << std::endl; - oss << " End offset (_eo) = 0x" << std::hex << _eo << std::dec << " (" << - (_eo/JRNL_DBLK_SIZE) << " dblks)" << std::endl; - oss << " Highest rid (_h_rid) = 0x" << std::hex << _h_rid << std::dec << std::endl; - oss << " Last file full (_lffull) = " << (_lffull ? "TRUE" : "FALSE") << std::endl; - oss << " Journal full (_jfull) = " << (_jfull ? "TRUE" : "FALSE") << std::endl; - oss << " Normalized fid list (_fid_list) = ["; - for (std::vector::const_iterator i = _fid_list.begin(); i < _fid_list.end(); i++) - { - if (i != _fid_list.begin()) oss << ", "; - oss << *i; - } - oss << "]" << std::endl; - oss << " Enqueued records (txn & non-txn):" << std::endl; - for (unsigned i=0; i<_enq_cnt_list.size(); i++) - oss << " File " << std::setw(2) << i << ": " << _enq_cnt_list[i] << - std::endl; - return oss.str(); - } - - std::string to_log(const std::string& jid) - { - std::ostringstream oss; - oss << "Recover file analysis (jid=\"" << jid << "\"):"; - oss << " njf=" << _njf; - oss << " ae=" << (_owi ? "T" : "F"); - oss << " aemjf=" << _aemjf; - oss << " owi=" << (_ae ? "T" : "F"); - oss << " frot=" << (_frot ? "T" : "F"); - oss << " jempty=" << (_jempty ? "T" : "F"); - oss << " ffid=" << _ffid; - oss << " fro=0x" << std::hex << _fro << std::dec << " (" << - (_fro/JRNL_DBLK_SIZE) << " dblks)"; - oss << " lfid=" << _lfid; - oss << " eo=0x" << std::hex << _eo << std::dec << " (" << - (_eo/JRNL_DBLK_SIZE) << " dblks)"; - oss << " h_rid=0x" << std::hex << _h_rid << std::dec; - oss << " lffull=" << (_lffull ? "T" : "F"); - oss << " jfull=" << (_jfull ? "T" : "F"); - oss << " Enqueued records (txn & non-txn): [ "; - for (unsigned i=0; i<_enq_cnt_list.size(); i++) - { - if (i) oss << " "; - oss << "fid_" << std::setw(2) << std::setfill('0') << i << "=" << _enq_cnt_list[i]; - } - oss << " ]"; - return oss.str(); - } - }; -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_rcvdat_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rec_hdr.h b/cpp/src/qpid/legacystore/jrnl/rec_hdr.h new file mode 100644 index 0000000000..852aabd7b6 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/rec_hdr.h @@ -0,0 +1,143 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file rec_hdr.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::rec_hdr (record header), + * which is a common initial header used for all journal record structures + * except the record tail (rec_tail). + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_rec_hdr_hpp +#define mrg_journal_rec_hdr_hpp + +#include +#include "jrnl/jcfg.hpp" +#include + +namespace mrg +{ +namespace journal +{ + +#pragma pack(1) + + /** + * \brief Struct for data common to the head of all journal files and records. + * This includes identification for the file type, the encoding version, endian + * indicator and a record ID. + * + * File header info in binary format (16 bytes): + *
+    *   0                           7
+    * +---+---+---+---+---+---+---+---+
+    * |     magic     | v | e | flags |
+    * +---+---+---+---+---+---+---+---+
+    * |              rid              |
+    * +---+---+---+---+---+---+---+---+
+    * v = file version (If the format or encoding of this file changes, then this
+    *     number should be incremented)
+    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
+    * 
+ * + * Note that journal files should be transferable between 32- and 64-bit + * hardware of the same endianness, but not between hardware of opposite + * entianness without some sort of binary conversion utility. Thus buffering + * will be needed for types that change size between 32- and 64-bit compiles. + */ + struct rec_hdr + { + u_int32_t _magic; ///< File type identifier (magic number) + u_int8_t _version; ///< File encoding version + u_int8_t _eflag; ///< Flag for determining endianness + u_int16_t _uflag; ///< User-defined flags + u_int64_t _rid; ///< Record ID (rotating 64-bit counter) + + // Global flags + static const u_int16_t HDR_OVERWRITE_INDICATOR_MASK = 0x1; + + // Convenience constructors and methods + /** + * \brief Default constructor, which sets all values to 0. + */ + inline rec_hdr(): _magic(0), _version(0), _eflag(0), _uflag(0), _rid(0) {} + + /** + * \brief Convenience constructor which initializes values during construction. + */ + inline rec_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, + const bool owi): _magic(magic), _version(version), +#if defined(JRNL_BIG_ENDIAN) + _eflag(RHM_BENDIAN_FLAG), +#else + _eflag(RHM_LENDIAN_FLAG), +#endif + _uflag(owi ? HDR_OVERWRITE_INDICATOR_MASK : 0), _rid(rid) {} + + /** + * \brief Convenience copy method. + */ + inline void hdr_copy(const rec_hdr& h) + { + _magic = h._magic; + _version = h._version; + _eflag = h._eflag; + _uflag = h._uflag; + _rid =h._rid; + } + + /** + * \brief Resets all fields to 0 + */ + inline void reset() + { + _magic = 0; + _version = 0; + _eflag = 0; + _uflag = 0; + _rid = 0; + } + + inline bool get_owi() const { return _uflag & HDR_OVERWRITE_INDICATOR_MASK; } + + inline void set_owi(const bool owi) + { + _uflag = owi ? _uflag | HDR_OVERWRITE_INDICATOR_MASK : + _uflag & (~HDR_OVERWRITE_INDICATOR_MASK); + } + + /** + * \brief Returns the size of the header in bytes. + */ + inline static std::size_t size() { return sizeof(rec_hdr); } + }; // struct rec_hdr + +#pragma pack() + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_rec_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rec_hdr.hpp b/cpp/src/qpid/legacystore/jrnl/rec_hdr.hpp deleted file mode 100644 index 852aabd7b6..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/rec_hdr.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file rec_hdr.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rec_hdr (record header), - * which is a common initial header used for all journal record structures - * except the record tail (rec_tail). - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_rec_hdr_hpp -#define mrg_journal_rec_hdr_hpp - -#include -#include "jrnl/jcfg.hpp" -#include - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for data common to the head of all journal files and records. - * This includes identification for the file type, the encoding version, endian - * indicator and a record ID. - * - * File header info in binary format (16 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+
-    * |     magic     | v | e | flags |
-    * +---+---+---+---+---+---+---+---+
-    * |              rid              |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct rec_hdr - { - u_int32_t _magic; ///< File type identifier (magic number) - u_int8_t _version; ///< File encoding version - u_int8_t _eflag; ///< Flag for determining endianness - u_int16_t _uflag; ///< User-defined flags - u_int64_t _rid; ///< Record ID (rotating 64-bit counter) - - // Global flags - static const u_int16_t HDR_OVERWRITE_INDICATOR_MASK = 0x1; - - // Convenience constructors and methods - /** - * \brief Default constructor, which sets all values to 0. - */ - inline rec_hdr(): _magic(0), _version(0), _eflag(0), _uflag(0), _rid(0) {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline rec_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const bool owi): _magic(magic), _version(version), -#if defined(JRNL_BIG_ENDIAN) - _eflag(RHM_BENDIAN_FLAG), -#else - _eflag(RHM_LENDIAN_FLAG), -#endif - _uflag(owi ? HDR_OVERWRITE_INDICATOR_MASK : 0), _rid(rid) {} - - /** - * \brief Convenience copy method. - */ - inline void hdr_copy(const rec_hdr& h) - { - _magic = h._magic; - _version = h._version; - _eflag = h._eflag; - _uflag = h._uflag; - _rid =h._rid; - } - - /** - * \brief Resets all fields to 0 - */ - inline void reset() - { - _magic = 0; - _version = 0; - _eflag = 0; - _uflag = 0; - _rid = 0; - } - - inline bool get_owi() const { return _uflag & HDR_OVERWRITE_INDICATOR_MASK; } - - inline void set_owi(const bool owi) - { - _uflag = owi ? _uflag | HDR_OVERWRITE_INDICATOR_MASK : - _uflag & (~HDR_OVERWRITE_INDICATOR_MASK); - } - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(rec_hdr); } - }; // struct rec_hdr - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_rec_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rec_tail.h b/cpp/src/qpid/legacystore/jrnl/rec_tail.h new file mode 100644 index 0000000000..914e21d5c9 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/rec_tail.h @@ -0,0 +1,98 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file rec_tail.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::rec_tail (record tail), used to + * finalize a persistent record. The presence of a valid tail at the expected + * position in the journal file indicates that the record write was completed. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_rec_tail_hpp +#define mrg_journal_rec_tail_hpp + +#include +#include "jrnl/jcfg.hpp" + +namespace mrg +{ +namespace journal +{ + +#pragma pack(1) + + /** + * \brief Struct for data common to the tail of all records. The magic number + * used here is the binary inverse (1's complement) of the magic used in the + * record header; this minimizes possible confusion with other headers that may + * be present during recovery. The tail is used with all records that have either + * XIDs or data - ie any size-variable content. Currently the only records that + * do NOT use the tail are non-transactional dequeues and filler records. + * + * Record header info in binary format (12 bytes): + *
+    *   0                           7
+    * +---+---+---+---+---+---+---+---+
+    * |   ~(magic)    |      rid      |
+    * +---+---+---+---+---+---+---+---+
+    * |  rid (con't)  |
+    * +---+---+---+---+
+    * 
+ */ + struct rec_tail + { + u_int32_t _xmagic; ///< Binary inverse (1's complement) of hdr magic number + u_int64_t _rid; ///< ID (rotating 64-bit counter) + + + /** + * \brief Default constructor, which sets all values to 0. + */ + inline rec_tail(): _xmagic(0xffffffff), _rid(0) {} + + /** + * \brief Convenience constructor which initializes values during construction from + * existing enq_hdr instance. + */ + inline rec_tail(const rec_hdr& h): _xmagic(~h._magic), _rid(h._rid) {} + + /** + * \brief Convenience constructor which initializes values during construction. + */ + inline rec_tail(const u_int32_t xmagic, const u_int64_t rid): _xmagic(xmagic), _rid(rid) {} + + /** + * \brief Returns the size of the header in bytes. + */ + inline static std::size_t size() { return sizeof(rec_tail); } + }; + +#pragma pack() + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_rec_tail_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rec_tail.hpp b/cpp/src/qpid/legacystore/jrnl/rec_tail.hpp deleted file mode 100644 index 914e21d5c9..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/rec_tail.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file rec_tail.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rec_tail (record tail), used to - * finalize a persistent record. The presence of a valid tail at the expected - * position in the journal file indicates that the record write was completed. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_rec_tail_hpp -#define mrg_journal_rec_tail_hpp - -#include -#include "jrnl/jcfg.hpp" - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for data common to the tail of all records. The magic number - * used here is the binary inverse (1's complement) of the magic used in the - * record header; this minimizes possible confusion with other headers that may - * be present during recovery. The tail is used with all records that have either - * XIDs or data - ie any size-variable content. Currently the only records that - * do NOT use the tail are non-transactional dequeues and filler records. - * - * Record header info in binary format (12 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+
-    * |   ~(magic)    |      rid      |
-    * +---+---+---+---+---+---+---+---+
-    * |  rid (con't)  |
-    * +---+---+---+---+
-    * 
- */ - struct rec_tail - { - u_int32_t _xmagic; ///< Binary inverse (1's complement) of hdr magic number - u_int64_t _rid; ///< ID (rotating 64-bit counter) - - - /** - * \brief Default constructor, which sets all values to 0. - */ - inline rec_tail(): _xmagic(0xffffffff), _rid(0) {} - - /** - * \brief Convenience constructor which initializes values during construction from - * existing enq_hdr instance. - */ - inline rec_tail(const rec_hdr& h): _xmagic(~h._magic), _rid(h._rid) {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline rec_tail(const u_int32_t xmagic, const u_int64_t rid): _xmagic(xmagic), _rid(rid) {} - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(rec_tail); } - }; - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_rec_tail_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rfc.h b/cpp/src/qpid/legacystore/jrnl/rfc.h new file mode 100644 index 0000000000..6b0483da5a --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/rfc.h @@ -0,0 +1,193 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file rfc.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::rfc (rotating + * file controller). See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_rfc_hpp +#define mrg_journal_rfc_hpp + +namespace mrg +{ +namespace journal +{ +class rfc; +} +} + +#include "jrnl/lpmgr.hpp" +#include "jrnl/enums.hpp" + +namespace mrg +{ +namespace journal +{ + + /** + * \class rfc + * \brief Rotating File Controller (rfc) - Class to handle the manangement of an array of file controllers (fcntl) + * objects for use in a circular disk buffer (journal). Each fcntl object corresponds to a file in the journal. + * + * The following states exist in this class: + * + *
+    *                                                                   is_init()  is_active()
+    *                  +===+                    _lpmp.is_init() == false
+    *      +---------->|   |     Uninitialized: _curr_fc == 0               F           F
+    *      |       +-->+===+ --+
+    *      |       |           |
+    *      |       |           |
+    *      |   finalize()   initialize()
+    *      |       |           |
+    *      |       |           |
+    *      |       +-- +===+<--+                _lpmp.is_init() == true
+    *  finalize()      |   |     Inactive:      _curr_fc == 0               T           F
+    *      |       +-->+===+ --+
+    *      |       |           |
+    *      |       |           |
+    *      | unset_findex() set_findex()
+    *      |       |           |
+    *      |       |           |
+    *      |       +-- +===+<--+                _lpmp.is_init() == true
+    *      +---------- |   |     Active:        _curr_fc != 0               T           T
+    *                  +===+
+    * 
+ * + * The Uninitialized state is where the class starts after construction. Once the number of files is known and + * the array of file controllers allocated, then initialize() is called to set these, causing the state to move + * to Inactive. + * + * The Inactive state has the file controllers allocated and pointing to their respective journal files, but no + * current file controller has been selected. The pointer to the current file controller _curr_fc is null. Once the + * index of the active file is known, then calling set_findex() will set the index and internal pointer + * to the currently active file controller. This moves the state to Active. + * + * Note TODO: Comment on sync issues between change in num files in _lpmp and _fc_index/_curr_fc. + */ + class rfc + { + protected: + const lpmgr* _lpmp; ///< Pointer to jcntl's lpmgr instance containing lfid/pfid map and fcntl objects + u_int16_t _fc_index; ///< Index of current file controller + fcntl* _curr_fc; ///< Pointer to current file controller + + public: + rfc(const lpmgr* lpmp); + virtual ~rfc(); + + /** + * \brief Initialize the controller, moving from state Uninitialized to Inactive. The main function of + * initialize() is to set the number of files and the pointer to the fcntl array. + */ + virtual inline void initialize() {} + + /** + * \brief Reset the controller to Uninitialized state, usually called when the journal is stopped. Once called, + * initialize() must be called to reuse an instance. + */ + virtual void finalize(); + + /** + * \brief Check initialization state: true = Not Uninitialized, ie Initialized or Active; false = Uninitialized. + */ + virtual inline bool is_init() const { return _lpmp->is_init(); } + + /** + * \brief Check active state: true = Initialized and _curr_fc not null; false otherwise. + */ + virtual inline bool is_active() const { return _lpmp->is_init() && _curr_fc != 0; } + + /** + * \brief Sets the current file index and active fcntl object. Moves to state Active. + */ + virtual void set_findex(const u_int16_t fc_index); + + /** + * \brief Nulls the current file index and active fcntl pointer, moves to state Inactive. + */ + virtual void unset_findex(); + + /** + * \brief Rotate active file controller to next file in rotating file group. + * \exception jerrno::JERR__NINIT if called before calling initialize(). + */ + virtual iores rotate() = 0; + + /** + * \brief Returns the index of the currently active file within the rotating file group. + */ + inline u_int16_t index() const { return _fc_index; } + + /** + * \brief Returns the currently active journal file controller within the rotating file group. + */ + inline fcntl* file_controller() const { return _curr_fc; } + + /** + * \brief Returns the currently active physical file id (pfid) + */ + inline u_int16_t pfid() const { return _curr_fc->pfid(); } + + // Convenience access methods to current file controller + // Note: Do not call when not in active state + + inline u_int32_t enqcnt() const { return _curr_fc->enqcnt(); } + inline u_int32_t incr_enqcnt() { return _curr_fc->incr_enqcnt(); } + inline u_int32_t incr_enqcnt(const u_int16_t fid) { return _lpmp->get_fcntlp(fid)->incr_enqcnt(); } + inline u_int32_t add_enqcnt(const u_int32_t a) { return _curr_fc->add_enqcnt(a); } + inline u_int32_t add_enqcnt(const u_int16_t fid, const u_int32_t a) + { return _lpmp->get_fcntlp(fid)->add_enqcnt(a); } + inline u_int32_t decr_enqcnt(const u_int16_t fid) { return _lpmp->get_fcntlp(fid)->decr_enqcnt(); } + inline u_int32_t subtr_enqcnt(const u_int16_t fid, const u_int32_t s) + { return _lpmp->get_fcntlp(fid)->subtr_enqcnt(s); } + + virtual inline u_int32_t subm_cnt_dblks() const = 0; + virtual inline std::size_t subm_offs() const = 0; + virtual inline u_int32_t add_subm_cnt_dblks(u_int32_t a) = 0; + + virtual inline u_int32_t cmpl_cnt_dblks() const = 0; + virtual inline std::size_t cmpl_offs() const = 0; + virtual inline u_int32_t add_cmpl_cnt_dblks(u_int32_t a) = 0; + + virtual inline bool is_void() const = 0; + virtual inline bool is_empty() const = 0; + virtual inline u_int32_t remaining_dblks() const = 0; + virtual inline bool is_full() const = 0; + virtual inline bool is_compl() const = 0; + virtual inline u_int32_t aio_outstanding_dblks() const = 0; + virtual inline bool file_rotate() const = 0; + + // Debug aid + virtual std::string status_str() const; + }; // class rfc + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_rfc_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rfc.hpp b/cpp/src/qpid/legacystore/jrnl/rfc.hpp deleted file mode 100644 index 6b0483da5a..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/rfc.hpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file rfc.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rfc (rotating - * file controller). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_rfc_hpp -#define mrg_journal_rfc_hpp - -namespace mrg -{ -namespace journal -{ -class rfc; -} -} - -#include "jrnl/lpmgr.hpp" -#include "jrnl/enums.hpp" - -namespace mrg -{ -namespace journal -{ - - /** - * \class rfc - * \brief Rotating File Controller (rfc) - Class to handle the manangement of an array of file controllers (fcntl) - * objects for use in a circular disk buffer (journal). Each fcntl object corresponds to a file in the journal. - * - * The following states exist in this class: - * - *
-    *                                                                   is_init()  is_active()
-    *                  +===+                    _lpmp.is_init() == false
-    *      +---------->|   |     Uninitialized: _curr_fc == 0               F           F
-    *      |       +-->+===+ --+
-    *      |       |           |
-    *      |       |           |
-    *      |   finalize()   initialize()
-    *      |       |           |
-    *      |       |           |
-    *      |       +-- +===+<--+                _lpmp.is_init() == true
-    *  finalize()      |   |     Inactive:      _curr_fc == 0               T           F
-    *      |       +-->+===+ --+
-    *      |       |           |
-    *      |       |           |
-    *      | unset_findex() set_findex()
-    *      |       |           |
-    *      |       |           |
-    *      |       +-- +===+<--+                _lpmp.is_init() == true
-    *      +---------- |   |     Active:        _curr_fc != 0               T           T
-    *                  +===+
-    * 
- * - * The Uninitialized state is where the class starts after construction. Once the number of files is known and - * the array of file controllers allocated, then initialize() is called to set these, causing the state to move - * to Inactive. - * - * The Inactive state has the file controllers allocated and pointing to their respective journal files, but no - * current file controller has been selected. The pointer to the current file controller _curr_fc is null. Once the - * index of the active file is known, then calling set_findex() will set the index and internal pointer - * to the currently active file controller. This moves the state to Active. - * - * Note TODO: Comment on sync issues between change in num files in _lpmp and _fc_index/_curr_fc. - */ - class rfc - { - protected: - const lpmgr* _lpmp; ///< Pointer to jcntl's lpmgr instance containing lfid/pfid map and fcntl objects - u_int16_t _fc_index; ///< Index of current file controller - fcntl* _curr_fc; ///< Pointer to current file controller - - public: - rfc(const lpmgr* lpmp); - virtual ~rfc(); - - /** - * \brief Initialize the controller, moving from state Uninitialized to Inactive. The main function of - * initialize() is to set the number of files and the pointer to the fcntl array. - */ - virtual inline void initialize() {} - - /** - * \brief Reset the controller to Uninitialized state, usually called when the journal is stopped. Once called, - * initialize() must be called to reuse an instance. - */ - virtual void finalize(); - - /** - * \brief Check initialization state: true = Not Uninitialized, ie Initialized or Active; false = Uninitialized. - */ - virtual inline bool is_init() const { return _lpmp->is_init(); } - - /** - * \brief Check active state: true = Initialized and _curr_fc not null; false otherwise. - */ - virtual inline bool is_active() const { return _lpmp->is_init() && _curr_fc != 0; } - - /** - * \brief Sets the current file index and active fcntl object. Moves to state Active. - */ - virtual void set_findex(const u_int16_t fc_index); - - /** - * \brief Nulls the current file index and active fcntl pointer, moves to state Inactive. - */ - virtual void unset_findex(); - - /** - * \brief Rotate active file controller to next file in rotating file group. - * \exception jerrno::JERR__NINIT if called before calling initialize(). - */ - virtual iores rotate() = 0; - - /** - * \brief Returns the index of the currently active file within the rotating file group. - */ - inline u_int16_t index() const { return _fc_index; } - - /** - * \brief Returns the currently active journal file controller within the rotating file group. - */ - inline fcntl* file_controller() const { return _curr_fc; } - - /** - * \brief Returns the currently active physical file id (pfid) - */ - inline u_int16_t pfid() const { return _curr_fc->pfid(); } - - // Convenience access methods to current file controller - // Note: Do not call when not in active state - - inline u_int32_t enqcnt() const { return _curr_fc->enqcnt(); } - inline u_int32_t incr_enqcnt() { return _curr_fc->incr_enqcnt(); } - inline u_int32_t incr_enqcnt(const u_int16_t fid) { return _lpmp->get_fcntlp(fid)->incr_enqcnt(); } - inline u_int32_t add_enqcnt(const u_int32_t a) { return _curr_fc->add_enqcnt(a); } - inline u_int32_t add_enqcnt(const u_int16_t fid, const u_int32_t a) - { return _lpmp->get_fcntlp(fid)->add_enqcnt(a); } - inline u_int32_t decr_enqcnt(const u_int16_t fid) { return _lpmp->get_fcntlp(fid)->decr_enqcnt(); } - inline u_int32_t subtr_enqcnt(const u_int16_t fid, const u_int32_t s) - { return _lpmp->get_fcntlp(fid)->subtr_enqcnt(s); } - - virtual inline u_int32_t subm_cnt_dblks() const = 0; - virtual inline std::size_t subm_offs() const = 0; - virtual inline u_int32_t add_subm_cnt_dblks(u_int32_t a) = 0; - - virtual inline u_int32_t cmpl_cnt_dblks() const = 0; - virtual inline std::size_t cmpl_offs() const = 0; - virtual inline u_int32_t add_cmpl_cnt_dblks(u_int32_t a) = 0; - - virtual inline bool is_void() const = 0; - virtual inline bool is_empty() const = 0; - virtual inline u_int32_t remaining_dblks() const = 0; - virtual inline bool is_full() const = 0; - virtual inline bool is_compl() const = 0; - virtual inline u_int32_t aio_outstanding_dblks() const = 0; - virtual inline bool file_rotate() const = 0; - - // Debug aid - virtual std::string status_str() const; - }; // class rfc - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_rfc_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rmgr.h b/cpp/src/qpid/legacystore/jrnl/rmgr.h new file mode 100644 index 0000000000..8f053b9dfc --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/rmgr.h @@ -0,0 +1,114 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file rmgr.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::rmgr (read manager). See + * class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_rmgr_hpp +#define mrg_journal_rmgr_hpp + +namespace mrg +{ +namespace journal +{ +class rmgr; +} +} + +#include +#include "jrnl/enums.hpp" +#include "jrnl/file_hdr.hpp" +#include "jrnl/pmgr.hpp" +#include "jrnl/rec_hdr.hpp" +#include "jrnl/rrfc.hpp" + +namespace mrg +{ +namespace journal +{ + + /** + * \brief Class for managing a read page cache of arbitrary size and number of pages. + * + * The read page cache works on the principle of filling as many pages as possilbe in advance of + * reading the data. This ensures that delays caused by AIO operations are minimized. + */ + class rmgr : public pmgr + { + private: + rrfc& _rrfc; ///< Ref to read rotating file controller + rec_hdr _hdr; ///< Header used to determind record type + + void* _fhdr_buffer; ///< Buffer used for fhdr reads + aio_cb* _fhdr_aio_cb_ptr; ///< iocb pointer for fhdr reads + file_hdr _fhdr; ///< file header instance for reading file headers + bool _fhdr_rd_outstanding; ///< true if a fhdr read is outstanding + + public: + rmgr(jcntl* jc, enq_map& emap, txn_map& tmap, rrfc& rrfc); + virtual ~rmgr(); + + using pmgr::initialize; + void initialize(aio_callback* const cbp); + iores read(void** const datapp, std::size_t& dsize, void** const xidpp, + std::size_t& xidsize, bool& transient, bool& external, data_tok* dtokp, + bool ignore_pending_txns); + int32_t get_events(page_state state, timespec* const timeout, bool flush = false); + void recover_complete(); + inline iores synchronize() { if (_rrfc.is_valid()) return RHM_IORES_SUCCESS; return aio_cycle(); } + void invalidate(); + bool wait_for_validity(timespec* const timeout, const bool throw_on_timeout = false); + + /* TODO (if required) + const iores get(const u_int64_t& rid, const std::size_t& dsize, const std::size_t& dsize_avail, + const void** const data, bool auto_discard); + const iores discard(data_tok* dtok); + */ + + private: + void clean(); + void flush(timespec* timeout); + iores pre_read_check(data_tok* dtokp); + iores read_enq(rec_hdr& h, void* rptr, data_tok* dtokp); + void consume_xid_rec(rec_hdr& h, void* rptr, data_tok* dtokp); + void consume_filler(); + iores skip(data_tok* dtokp); + iores aio_cycle(); + iores init_aio_reads(const int16_t first_uninit, const u_int16_t num_uninit); + void rotate_page(); + u_int32_t dblks_rem() const; + void set_params_null(void** const datapp, std::size_t& dsize, void** const xidpp, + std::size_t& xidsize); + void init_file_header_read(); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_rmgr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rmgr.hpp b/cpp/src/qpid/legacystore/jrnl/rmgr.hpp deleted file mode 100644 index 8f053b9dfc..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/rmgr.hpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file rmgr.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rmgr (read manager). See - * class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_rmgr_hpp -#define mrg_journal_rmgr_hpp - -namespace mrg -{ -namespace journal -{ -class rmgr; -} -} - -#include -#include "jrnl/enums.hpp" -#include "jrnl/file_hdr.hpp" -#include "jrnl/pmgr.hpp" -#include "jrnl/rec_hdr.hpp" -#include "jrnl/rrfc.hpp" - -namespace mrg -{ -namespace journal -{ - - /** - * \brief Class for managing a read page cache of arbitrary size and number of pages. - * - * The read page cache works on the principle of filling as many pages as possilbe in advance of - * reading the data. This ensures that delays caused by AIO operations are minimized. - */ - class rmgr : public pmgr - { - private: - rrfc& _rrfc; ///< Ref to read rotating file controller - rec_hdr _hdr; ///< Header used to determind record type - - void* _fhdr_buffer; ///< Buffer used for fhdr reads - aio_cb* _fhdr_aio_cb_ptr; ///< iocb pointer for fhdr reads - file_hdr _fhdr; ///< file header instance for reading file headers - bool _fhdr_rd_outstanding; ///< true if a fhdr read is outstanding - - public: - rmgr(jcntl* jc, enq_map& emap, txn_map& tmap, rrfc& rrfc); - virtual ~rmgr(); - - using pmgr::initialize; - void initialize(aio_callback* const cbp); - iores read(void** const datapp, std::size_t& dsize, void** const xidpp, - std::size_t& xidsize, bool& transient, bool& external, data_tok* dtokp, - bool ignore_pending_txns); - int32_t get_events(page_state state, timespec* const timeout, bool flush = false); - void recover_complete(); - inline iores synchronize() { if (_rrfc.is_valid()) return RHM_IORES_SUCCESS; return aio_cycle(); } - void invalidate(); - bool wait_for_validity(timespec* const timeout, const bool throw_on_timeout = false); - - /* TODO (if required) - const iores get(const u_int64_t& rid, const std::size_t& dsize, const std::size_t& dsize_avail, - const void** const data, bool auto_discard); - const iores discard(data_tok* dtok); - */ - - private: - void clean(); - void flush(timespec* timeout); - iores pre_read_check(data_tok* dtokp); - iores read_enq(rec_hdr& h, void* rptr, data_tok* dtokp); - void consume_xid_rec(rec_hdr& h, void* rptr, data_tok* dtokp); - void consume_filler(); - iores skip(data_tok* dtokp); - iores aio_cycle(); - iores init_aio_reads(const int16_t first_uninit, const u_int16_t num_uninit); - void rotate_page(); - u_int32_t dblks_rem() const; - void set_params_null(void** const datapp, std::size_t& dsize, void** const xidpp, - std::size_t& xidsize); - void init_file_header_read(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_rmgr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rrfc.h b/cpp/src/qpid/legacystore/jrnl/rrfc.h new file mode 100644 index 0000000000..afd5f71f3c --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/rrfc.h @@ -0,0 +1,179 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file rrfc.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::rrfc (rotating + * file controller). See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_rrfc_hpp +#define mrg_journal_rrfc_hpp + +namespace mrg +{ +namespace journal +{ +class rrfc; +} +} + +#include "jrnl/fcntl.hpp" +#include "jrnl/rfc.hpp" + +namespace mrg +{ +namespace journal +{ + + /** + * \class rrfc + * \brief Read Rotating File Controller (rrfc) - Subclassed from pure virtual class rfc. Used to control the read + * pipeline in a rotating file buffer or journal. See class rfc for further details. + * + * The states that exist in this class are identical to class rfc from which it inherits, but in addition, the value + * of the read file handle _fh is also considered. The calls to set_findex also opens the file handle _fh to the + * active file for reading. Similarly, unset_findex() closes this file handle. + * + *
+    *                                                                   is_init()  is_active()
+    *                  +===+                    _lpmp.is_init() == false
+    *      +---------->|   |     Uninitialized: _curr_fc == 0               F           F
+    *      |       +-->+===+ --+                _fh == -1
+    *      |       |           |
+    *      |       |           |
+    *      |   finalize()   initialize()
+    *      |       |           |
+    *      |       |           |
+    *      |       +-- +===+<--+                _lpmp.is_init() == true
+    *  finalize()      |   |     Inactive:      _curr_fc == 0               T           F
+    *      |       +-->+===+ --+                _fh == -1
+    *      |       |           |
+    *      |       |           |
+    *      | unset_findex() set_findex()
+    *      |       |           |
+    *      |       |           |
+    *      |       +-- +===+<--+                _lpmp.is_init() == true
+    *      +---------- |   |     Active:        _curr_fc != 0               T           T
+    *                  +===+                    _fh >= 0
+    * 
+ * + * In adition to the states above, class rrfc contains a validity flag. This is operated indepenedently of the state + * machine. This flag (_valid) indicates when the read buffers are valid for reading. This is not strictly a state, + * but simply a flag used to keep track of the status, and is set/unset with calls to set_valid() and set_invalid() + * respectively. + */ + class rrfc : public rfc + { + protected: + int _fh; ///< Read file handle + bool _valid; ///< Flag is true when read pages contain vailid data + + public: + rrfc(const lpmgr* lpmp); + virtual ~rrfc(); + + /** + * \brief Initialize the controller, moving from state Uninitialized to Initialized. The main function of + * initialize() is to set the number of files and the pointer to the fcntl array. + */ + inline void initialize() { rfc::initialize(); _valid = false; } + + /** + * \brief Reset the controller to Uninitialized state, usually called when the journal is stopped. Once called, + * initialize() must be called to reuse an instance. + */ + void finalize(); + + /** + * \brief Opens the file handle for reading a particular fid. Moves to state open. + */ + void set_findex(const u_int16_t fc_index); + + /** + * \brief Closes the read file handle and nulls the active fcntl pointer. Moves to state closed. + */ + void unset_findex(); + + /** + * \brief Check the state: true = open; false = closed. + */ + inline bool is_active() const { return _curr_fc != 0 && _fh >= 0; } + + /** + * \brief Sets the validity flag which indicates that the read buffers contain valid data for reading. + */ + inline void set_invalid() { _valid = false; } + + /** + * \brief Resets the validity flag wich indicates that the read buffers are no longer synchronized and cannot + * be read whithout resynchronization. + */ + inline void set_valid() { _valid = true; } + + /** + * \brief Checks the read buffer validity status: true = valid, can be read; false = invalid, synchronization + * required. + */ + inline bool is_valid() const { return _valid; } + + /** + * \brief Rotate active file controller to next file in rotating file group. + * \exception jerrno::JERR__NINIT if called before calling initialize(). + */ + iores rotate(); + + inline int fh() const { return _fh; } + + inline u_int32_t subm_cnt_dblks() const { return _curr_fc->rd_subm_cnt_dblks(); } + inline std::size_t subm_offs() const { return _curr_fc->rd_subm_offs(); } + inline u_int32_t add_subm_cnt_dblks(u_int32_t a) { return _curr_fc->add_rd_subm_cnt_dblks(a); } + + inline u_int32_t cmpl_cnt_dblks() const { return _curr_fc->rd_cmpl_cnt_dblks(); } + inline std::size_t cmpl_offs() const { return _curr_fc->rd_cmpl_offs(); } + inline u_int32_t add_cmpl_cnt_dblks(u_int32_t a) { return _curr_fc->add_rd_cmpl_cnt_dblks(a); } + + inline bool is_void() const { return _curr_fc->rd_void(); } + inline bool is_empty() const { return _curr_fc->rd_empty(); } + inline u_int32_t remaining_dblks() const { return _curr_fc->rd_remaining_dblks(); } + inline bool is_full() const { return _curr_fc->is_rd_full(); } + inline bool is_compl() const { return _curr_fc->is_rd_compl(); } + inline u_int32_t aio_outstanding_dblks() const { return _curr_fc->rd_aio_outstanding_dblks(); } + inline bool file_rotate() const { return _curr_fc->rd_file_rotate(); } + inline bool is_wr_aio_outstanding() const { return _curr_fc->wr_aio_outstanding_dblks() > 0; } + + // Debug aid + std::string status_str() const; + + protected: + void open_fh(const std::string& fn); + void close_fh(); + }; // class rrfc + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_rrfc_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/rrfc.hpp b/cpp/src/qpid/legacystore/jrnl/rrfc.hpp deleted file mode 100644 index afd5f71f3c..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/rrfc.hpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file rrfc.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rrfc (rotating - * file controller). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_rrfc_hpp -#define mrg_journal_rrfc_hpp - -namespace mrg -{ -namespace journal -{ -class rrfc; -} -} - -#include "jrnl/fcntl.hpp" -#include "jrnl/rfc.hpp" - -namespace mrg -{ -namespace journal -{ - - /** - * \class rrfc - * \brief Read Rotating File Controller (rrfc) - Subclassed from pure virtual class rfc. Used to control the read - * pipeline in a rotating file buffer or journal. See class rfc for further details. - * - * The states that exist in this class are identical to class rfc from which it inherits, but in addition, the value - * of the read file handle _fh is also considered. The calls to set_findex also opens the file handle _fh to the - * active file for reading. Similarly, unset_findex() closes this file handle. - * - *
-    *                                                                   is_init()  is_active()
-    *                  +===+                    _lpmp.is_init() == false
-    *      +---------->|   |     Uninitialized: _curr_fc == 0               F           F
-    *      |       +-->+===+ --+                _fh == -1
-    *      |       |           |
-    *      |       |           |
-    *      |   finalize()   initialize()
-    *      |       |           |
-    *      |       |           |
-    *      |       +-- +===+<--+                _lpmp.is_init() == true
-    *  finalize()      |   |     Inactive:      _curr_fc == 0               T           F
-    *      |       +-->+===+ --+                _fh == -1
-    *      |       |           |
-    *      |       |           |
-    *      | unset_findex() set_findex()
-    *      |       |           |
-    *      |       |           |
-    *      |       +-- +===+<--+                _lpmp.is_init() == true
-    *      +---------- |   |     Active:        _curr_fc != 0               T           T
-    *                  +===+                    _fh >= 0
-    * 
- * - * In adition to the states above, class rrfc contains a validity flag. This is operated indepenedently of the state - * machine. This flag (_valid) indicates when the read buffers are valid for reading. This is not strictly a state, - * but simply a flag used to keep track of the status, and is set/unset with calls to set_valid() and set_invalid() - * respectively. - */ - class rrfc : public rfc - { - protected: - int _fh; ///< Read file handle - bool _valid; ///< Flag is true when read pages contain vailid data - - public: - rrfc(const lpmgr* lpmp); - virtual ~rrfc(); - - /** - * \brief Initialize the controller, moving from state Uninitialized to Initialized. The main function of - * initialize() is to set the number of files and the pointer to the fcntl array. - */ - inline void initialize() { rfc::initialize(); _valid = false; } - - /** - * \brief Reset the controller to Uninitialized state, usually called when the journal is stopped. Once called, - * initialize() must be called to reuse an instance. - */ - void finalize(); - - /** - * \brief Opens the file handle for reading a particular fid. Moves to state open. - */ - void set_findex(const u_int16_t fc_index); - - /** - * \brief Closes the read file handle and nulls the active fcntl pointer. Moves to state closed. - */ - void unset_findex(); - - /** - * \brief Check the state: true = open; false = closed. - */ - inline bool is_active() const { return _curr_fc != 0 && _fh >= 0; } - - /** - * \brief Sets the validity flag which indicates that the read buffers contain valid data for reading. - */ - inline void set_invalid() { _valid = false; } - - /** - * \brief Resets the validity flag wich indicates that the read buffers are no longer synchronized and cannot - * be read whithout resynchronization. - */ - inline void set_valid() { _valid = true; } - - /** - * \brief Checks the read buffer validity status: true = valid, can be read; false = invalid, synchronization - * required. - */ - inline bool is_valid() const { return _valid; } - - /** - * \brief Rotate active file controller to next file in rotating file group. - * \exception jerrno::JERR__NINIT if called before calling initialize(). - */ - iores rotate(); - - inline int fh() const { return _fh; } - - inline u_int32_t subm_cnt_dblks() const { return _curr_fc->rd_subm_cnt_dblks(); } - inline std::size_t subm_offs() const { return _curr_fc->rd_subm_offs(); } - inline u_int32_t add_subm_cnt_dblks(u_int32_t a) { return _curr_fc->add_rd_subm_cnt_dblks(a); } - - inline u_int32_t cmpl_cnt_dblks() const { return _curr_fc->rd_cmpl_cnt_dblks(); } - inline std::size_t cmpl_offs() const { return _curr_fc->rd_cmpl_offs(); } - inline u_int32_t add_cmpl_cnt_dblks(u_int32_t a) { return _curr_fc->add_rd_cmpl_cnt_dblks(a); } - - inline bool is_void() const { return _curr_fc->rd_void(); } - inline bool is_empty() const { return _curr_fc->rd_empty(); } - inline u_int32_t remaining_dblks() const { return _curr_fc->rd_remaining_dblks(); } - inline bool is_full() const { return _curr_fc->is_rd_full(); } - inline bool is_compl() const { return _curr_fc->is_rd_compl(); } - inline u_int32_t aio_outstanding_dblks() const { return _curr_fc->rd_aio_outstanding_dblks(); } - inline bool file_rotate() const { return _curr_fc->rd_file_rotate(); } - inline bool is_wr_aio_outstanding() const { return _curr_fc->wr_aio_outstanding_dblks() > 0; } - - // Debug aid - std::string status_str() const; - - protected: - void open_fh(const std::string& fn); - void close_fh(); - }; // class rrfc - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_rrfc_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/slock.h b/cpp/src/qpid/legacystore/jrnl/slock.h new file mode 100644 index 0000000000..2e8fc68c25 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/slock.h @@ -0,0 +1,85 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file slock.hpp + * + * Qpid asynchronous store plugin library + * + * Messaging journal scoped lock class mrg::journal::slock and scoped try-lock + * class mrg::journal::stlock. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_slock_hpp +#define mrg_journal_slock_hpp + +#include "jrnl/jexception.hpp" +#include "jrnl/smutex.hpp" +#include + +namespace mrg +{ +namespace journal +{ + + // Ultra-simple scoped lock class, auto-releases mutex when it goes out-of-scope + class slock + { + protected: + const smutex& _sm; + public: + inline slock(const smutex& sm) : _sm(sm) + { + PTHREAD_CHK(::pthread_mutex_lock(_sm.get()), "::pthread_mutex_lock", "slock", "slock"); + } + inline ~slock() + { + PTHREAD_CHK(::pthread_mutex_unlock(_sm.get()), "::pthread_mutex_unlock", "slock", "~slock"); + } + }; + + // Ultra-simple scoped try-lock class, auto-releases mutex when it goes out-of-scope + class stlock + { + protected: + const smutex& _sm; + bool _locked; + public: + inline stlock(const smutex& sm) : _sm(sm), _locked(false) + { + int ret = ::pthread_mutex_trylock(_sm.get()); + _locked = (ret == 0); // check if lock obtained + if (!_locked && ret != EBUSY) PTHREAD_CHK(ret, "::pthread_mutex_trylock", "stlock", "stlock"); + } + inline ~stlock() + { + if (_locked) + PTHREAD_CHK(::pthread_mutex_unlock(_sm.get()), "::pthread_mutex_unlock", "stlock", "~stlock"); + } + inline bool locked() const { return _locked; } + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_slock_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/slock.hpp b/cpp/src/qpid/legacystore/jrnl/slock.hpp deleted file mode 100644 index 2e8fc68c25..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/slock.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file slock.hpp - * - * Qpid asynchronous store plugin library - * - * Messaging journal scoped lock class mrg::journal::slock and scoped try-lock - * class mrg::journal::stlock. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_slock_hpp -#define mrg_journal_slock_hpp - -#include "jrnl/jexception.hpp" -#include "jrnl/smutex.hpp" -#include - -namespace mrg -{ -namespace journal -{ - - // Ultra-simple scoped lock class, auto-releases mutex when it goes out-of-scope - class slock - { - protected: - const smutex& _sm; - public: - inline slock(const smutex& sm) : _sm(sm) - { - PTHREAD_CHK(::pthread_mutex_lock(_sm.get()), "::pthread_mutex_lock", "slock", "slock"); - } - inline ~slock() - { - PTHREAD_CHK(::pthread_mutex_unlock(_sm.get()), "::pthread_mutex_unlock", "slock", "~slock"); - } - }; - - // Ultra-simple scoped try-lock class, auto-releases mutex when it goes out-of-scope - class stlock - { - protected: - const smutex& _sm; - bool _locked; - public: - inline stlock(const smutex& sm) : _sm(sm), _locked(false) - { - int ret = ::pthread_mutex_trylock(_sm.get()); - _locked = (ret == 0); // check if lock obtained - if (!_locked && ret != EBUSY) PTHREAD_CHK(ret, "::pthread_mutex_trylock", "stlock", "stlock"); - } - inline ~stlock() - { - if (_locked) - PTHREAD_CHK(::pthread_mutex_unlock(_sm.get()), "::pthread_mutex_unlock", "stlock", "~stlock"); - } - inline bool locked() const { return _locked; } - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_slock_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/smutex.h b/cpp/src/qpid/legacystore/jrnl/smutex.h new file mode 100644 index 0000000000..a0c21cbb4d --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/smutex.h @@ -0,0 +1,64 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file smutex.hpp + * + * Qpid asynchronous store plugin library + * + * Messaging journal scoped mutex class mrg::journal::smutex. + * + * \author Kim van der Riet + */ + + +#ifndef mrg_journal_smutex_hpp +#define mrg_journal_smutex_hpp + +#include "jrnl/jexception.hpp" +#include + +namespace mrg +{ +namespace journal +{ + + // Ultra-simple scoped mutex class that allows a posix mutex to be initialized and destroyed with error checks + class smutex + { + protected: + mutable pthread_mutex_t _m; + public: + inline smutex() + { + PTHREAD_CHK(::pthread_mutex_init(&_m, 0), "::pthread_mutex_init", "smutex", "smutex"); + } + inline virtual ~smutex() + { + PTHREAD_CHK(::pthread_mutex_destroy(&_m), "::pthread_mutex_destroy", "smutex", "~smutex"); + } + inline pthread_mutex_t* get() const { return &_m; } + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_smutex_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/smutex.hpp b/cpp/src/qpid/legacystore/jrnl/smutex.hpp deleted file mode 100644 index a0c21cbb4d..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/smutex.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file smutex.hpp - * - * Qpid asynchronous store plugin library - * - * Messaging journal scoped mutex class mrg::journal::smutex. - * - * \author Kim van der Riet - */ - - -#ifndef mrg_journal_smutex_hpp -#define mrg_journal_smutex_hpp - -#include "jrnl/jexception.hpp" -#include - -namespace mrg -{ -namespace journal -{ - - // Ultra-simple scoped mutex class that allows a posix mutex to be initialized and destroyed with error checks - class smutex - { - protected: - mutable pthread_mutex_t _m; - public: - inline smutex() - { - PTHREAD_CHK(::pthread_mutex_init(&_m, 0), "::pthread_mutex_init", "smutex", "smutex"); - } - inline virtual ~smutex() - { - PTHREAD_CHK(::pthread_mutex_destroy(&_m), "::pthread_mutex_destroy", "smutex", "~smutex"); - } - inline pthread_mutex_t* get() const { return &_m; } - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_smutex_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/time_ns.h b/cpp/src/qpid/legacystore/jrnl/time_ns.h new file mode 100644 index 0000000000..fd910f8e4c --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/time_ns.h @@ -0,0 +1,105 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file time_ns.hpp + * + * Qpid asynchronous store plugin library + * + * Messaging journal time struct mrg::journal::time_ns, derived from + * the timespec struct and provided with helper functions. + * + * \author Kim van der Riet + */ + +#ifndef mrg_jtt_time_ns_hpp +#define mrg_jtt_time_ns_hpp + +#include +#include +#include + +namespace mrg +{ +namespace journal +{ + +struct time_ns : public timespec +{ + inline time_ns() { tv_sec = 0; tv_nsec = 0; } + inline time_ns(const std::time_t sec, const long nsec = 0) { tv_sec = sec; tv_nsec = nsec; } + inline time_ns(const time_ns& t) { tv_sec = t.tv_sec; tv_nsec = t.tv_nsec; } + + inline void set_zero() { tv_sec = 0; tv_nsec = 0; } + inline bool is_zero() const { return tv_sec == 0 && tv_nsec == 0; } + inline int now() { if(::clock_gettime(CLOCK_REALTIME, this)) return errno; return 0; } + const std::string str(int precision = 6) const; + + inline time_ns& operator=(const time_ns& rhs) + { tv_sec = rhs.tv_sec; tv_nsec = rhs.tv_nsec; return *this; } + inline time_ns& operator+=(const time_ns& rhs) + { + tv_nsec += rhs.tv_nsec; + if (tv_nsec >= 1000000000L) { tv_sec++; tv_nsec -= 1000000000L; } + tv_sec += rhs.tv_sec; + return *this; + } + inline time_ns& operator+=(const long ns) + { + tv_nsec += ns; + if (tv_nsec >= 1000000000L) { tv_sec++; tv_nsec -= 1000000000L; } + return *this; + } + inline time_ns& operator-=(const long ns) + { + tv_nsec -= ns; + if (tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000L; } + return *this; + } + inline time_ns& operator-=(const time_ns& rhs) + { + tv_nsec -= rhs.tv_nsec; + if (tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000L; } + tv_sec -= rhs.tv_sec; + return *this; + } + inline const time_ns operator+(const time_ns& rhs) + { time_ns t(*this); t += rhs; return t; } + inline const time_ns operator-(const time_ns& rhs) + { time_ns t(*this); t -= rhs; return t; } + inline bool operator==(const time_ns& rhs) + { return tv_sec == rhs.tv_sec && tv_nsec == rhs.tv_nsec; } + inline bool operator!=(const time_ns& rhs) + { return tv_sec != rhs.tv_sec || tv_nsec != rhs.tv_nsec; } + inline bool operator>(const time_ns& rhs) + { if(tv_sec == rhs.tv_sec) return tv_nsec > rhs.tv_nsec; return tv_sec > rhs.tv_sec; } + inline bool operator>=(const time_ns& rhs) + { if(tv_sec == rhs.tv_sec) return tv_nsec >= rhs.tv_nsec; return tv_sec >= rhs.tv_sec; } + inline bool operator<(const time_ns& rhs) + { if(tv_sec == rhs.tv_sec) return tv_nsec < rhs.tv_nsec; return tv_sec < rhs.tv_sec; } + inline bool operator<=(const time_ns& rhs) + { if(tv_sec == rhs.tv_sec) return tv_nsec <= rhs.tv_nsec; return tv_sec <= rhs.tv_sec; } +}; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_jtt_time_ns_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/time_ns.hpp b/cpp/src/qpid/legacystore/jrnl/time_ns.hpp deleted file mode 100644 index fd910f8e4c..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/time_ns.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file time_ns.hpp - * - * Qpid asynchronous store plugin library - * - * Messaging journal time struct mrg::journal::time_ns, derived from - * the timespec struct and provided with helper functions. - * - * \author Kim van der Riet - */ - -#ifndef mrg_jtt_time_ns_hpp -#define mrg_jtt_time_ns_hpp - -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - -struct time_ns : public timespec -{ - inline time_ns() { tv_sec = 0; tv_nsec = 0; } - inline time_ns(const std::time_t sec, const long nsec = 0) { tv_sec = sec; tv_nsec = nsec; } - inline time_ns(const time_ns& t) { tv_sec = t.tv_sec; tv_nsec = t.tv_nsec; } - - inline void set_zero() { tv_sec = 0; tv_nsec = 0; } - inline bool is_zero() const { return tv_sec == 0 && tv_nsec == 0; } - inline int now() { if(::clock_gettime(CLOCK_REALTIME, this)) return errno; return 0; } - const std::string str(int precision = 6) const; - - inline time_ns& operator=(const time_ns& rhs) - { tv_sec = rhs.tv_sec; tv_nsec = rhs.tv_nsec; return *this; } - inline time_ns& operator+=(const time_ns& rhs) - { - tv_nsec += rhs.tv_nsec; - if (tv_nsec >= 1000000000L) { tv_sec++; tv_nsec -= 1000000000L; } - tv_sec += rhs.tv_sec; - return *this; - } - inline time_ns& operator+=(const long ns) - { - tv_nsec += ns; - if (tv_nsec >= 1000000000L) { tv_sec++; tv_nsec -= 1000000000L; } - return *this; - } - inline time_ns& operator-=(const long ns) - { - tv_nsec -= ns; - if (tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000L; } - return *this; - } - inline time_ns& operator-=(const time_ns& rhs) - { - tv_nsec -= rhs.tv_nsec; - if (tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000L; } - tv_sec -= rhs.tv_sec; - return *this; - } - inline const time_ns operator+(const time_ns& rhs) - { time_ns t(*this); t += rhs; return t; } - inline const time_ns operator-(const time_ns& rhs) - { time_ns t(*this); t -= rhs; return t; } - inline bool operator==(const time_ns& rhs) - { return tv_sec == rhs.tv_sec && tv_nsec == rhs.tv_nsec; } - inline bool operator!=(const time_ns& rhs) - { return tv_sec != rhs.tv_sec || tv_nsec != rhs.tv_nsec; } - inline bool operator>(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec > rhs.tv_nsec; return tv_sec > rhs.tv_sec; } - inline bool operator>=(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec >= rhs.tv_nsec; return tv_sec >= rhs.tv_sec; } - inline bool operator<(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec < rhs.tv_nsec; return tv_sec < rhs.tv_sec; } - inline bool operator<=(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec <= rhs.tv_nsec; return tv_sec <= rhs.tv_sec; } -}; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_jtt_time_ns_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/txn_hdr.h b/cpp/src/qpid/legacystore/jrnl/txn_hdr.h new file mode 100644 index 0000000000..e9a9b3137c --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/txn_hdr.h @@ -0,0 +1,125 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file txn_hdr.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::txn_hdr (transaction + * record header), used to start a transaction (commit or abort) record. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_txn_hdr_hpp +#define mrg_journal_txn_hdr_hpp + +#include +#include "jrnl/rec_hdr.hpp" + +namespace mrg +{ +namespace journal +{ + +#pragma pack(1) + + /** + * \brief Struct for transaction commit and abort records. + * + * Struct for DTX commit and abort records. Only the magic distinguishes between them. Since + * this record must be used in the context of a valid XID, the xidsize field must not be zero. + * Immediately following this record is the XID itself which is xidsize bytes long, followed by + * a rec_tail. + * + * Note that this record had its own rid distinct from the rids of the record(s) making up the + * transaction it is committing or aborting. + * + * Record header info in binary format (24 bytes): + *
+    *   0                           7
+    * +---+---+---+---+---+---+---+---+  -+
+    * |     magic     | v | e | flags |   |
+    * +---+---+---+---+---+---+---+---+   | struct hdr
+    * |              rid              |   |
+    * +---+---+---+---+---+---+---+---+  -+
+    * |            xidsize            |
+    * +---+---+---+---+---+---+---+---+
+    * v = file version (If the format or encoding of this file changes, then this
+    *     number should be incremented)
+    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
+    * 
+ * + * Note that journal files should be transferable between 32- and 64-bit + * hardware of the same endianness, but not between hardware of opposite + * entianness without some sort of binary conversion utility. Thus buffering + * will be needed for types that change size between 32- and 64-bit compiles. + */ + struct txn_hdr : rec_hdr + { +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t +#endif + std::size_t _xidsize; ///< XID size +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t +#endif + + /** + * \brief Default constructor, which sets all values to 0. + */ + txn_hdr(): rec_hdr(), +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif + _xidsize(0) +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + , _filler0(0) +#endif + {} + + /** + * \brief Convenience constructor which initializes values during construction. + */ + txn_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, + const std::size_t xidsize, const bool owi): rec_hdr(magic, version, rid, owi), +#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) + _filler0(0), +#endif + _xidsize(xidsize) +#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) + , _filler0(0) +#endif + {} + + /** + * \brief Returns the size of the header in bytes. + */ + inline static std::size_t size() { return sizeof(txn_hdr); } + }; + +#pragma pack() + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_txn_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/txn_hdr.hpp b/cpp/src/qpid/legacystore/jrnl/txn_hdr.hpp deleted file mode 100644 index e9a9b3137c..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/txn_hdr.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file txn_hdr.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::txn_hdr (transaction - * record header), used to start a transaction (commit or abort) record. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_txn_hdr_hpp -#define mrg_journal_txn_hdr_hpp - -#include -#include "jrnl/rec_hdr.hpp" - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for transaction commit and abort records. - * - * Struct for DTX commit and abort records. Only the magic distinguishes between them. Since - * this record must be used in the context of a valid XID, the xidsize field must not be zero. - * Immediately following this record is the XID itself which is xidsize bytes long, followed by - * a rec_tail. - * - * Note that this record had its own rid distinct from the rids of the record(s) making up the - * transaction it is committing or aborting. - * - * Record header info in binary format (24 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+  -+
-    * |     magic     | v | e | flags |   |
-    * +---+---+---+---+---+---+---+---+   | struct hdr
-    * |              rid              |   |
-    * +---+---+---+---+---+---+---+---+  -+
-    * |            xidsize            |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct txn_hdr : rec_hdr - { -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _xidsize; ///< XID size -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t -#endif - - /** - * \brief Default constructor, which sets all values to 0. - */ - txn_hdr(): rec_hdr(), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(0) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler0(0) -#endif - {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - txn_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const std::size_t xidsize, const bool owi): rec_hdr(magic, version, rid, owi), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(xidsize) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler0(0) -#endif - {} - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(txn_hdr); } - }; - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_txn_hdr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/txn_map.h b/cpp/src/qpid/legacystore/jrnl/txn_map.h new file mode 100644 index 0000000000..dab7aa76d1 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/txn_map.h @@ -0,0 +1,159 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file txn_map.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::txn_map (transaction map). + * See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_txn_map_hpp +#define mrg_journal_txn_map_hpp + +namespace mrg +{ +namespace journal +{ + class txn_map; +} +} + +#include "jrnl/smutex.hpp" +#include +#include +#include +#include +#include + +namespace mrg +{ +namespace journal +{ + + /** + * \struct txn_data_struct + * \brief Struct encapsulating transaction data necessary for processing a transaction + * in the journal once it is closed with either a commit or abort. + */ + struct txn_data_struct + { + u_int64_t _rid; ///< Record id for this operation + u_int64_t _drid; ///< Dequeue record id for this operation + u_int16_t _pfid; ///< Physical file id, to be used when transferring to emap on commit + bool _enq_flag; ///< If true, enq op, otherwise deq op + bool _commit_flag; ///< (2PC transactions) Records 2PC complete c/a mode + bool _aio_compl; ///< Initially false, set to true when record AIO returns + txn_data_struct(const u_int64_t rid, const u_int64_t drid, const u_int16_t pfid, + const bool enq_flag, const bool commit_flag = false); + }; + typedef txn_data_struct txn_data; + typedef std::vector txn_data_list; + typedef txn_data_list::iterator tdl_itr; + + /** + * \class txn_map + * \brief Class for storing transaction data for each open (ie not committed or aborted) + * xid in the store. If aborted, records are discarded; if committed, they are + * transferred to the enqueue map. + * + * The data is encapsulated by struct txn_data_struct. A vector containing the information + * for each operation included as part of the same transaction is mapped against the + * xid. + * + * The aio_compl flag is set true as each AIO write operation for the enqueue or dequeue + * returns. Checking that all of these flags are true for a given xid is the mechanism + * used to determine if the transaction is syncronized (through method is_txn_synced()). + * + * On transaction commit, then each operation is handled as follows: + * + * If an enqueue (_enq_flag is true), then the rid and pfid are transferred to the enq_map. + * If a dequeue (_enq_flag is false), then the rid stored in the drid field is used to + * remove the corresponding record from the enq_map. + * + * On transaction abort, then each operation is handled as follows: + * + * If an enqueue (_enq_flag is true), then the data is simply discarded. + * If a dequeue (_enq_flag is false), then the lock for the corresponding enqueue in enq_map + * (if not a part of the same transaction) is removed, and the data discarded. + * + *
+    *   key      data
+    *
+    *   xid1 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
+    *   xid2 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
+    *   xid3 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
+    *   ...
+    * 
+ */ + class txn_map + { + public: + // return/error codes + static int16_t TMAP_RID_NOT_FOUND; + static int16_t TMAP_XID_NOT_FOUND; + static int16_t TMAP_OK; + static int16_t TMAP_NOT_SYNCED; + static int16_t TMAP_SYNCED; + + private: + typedef std::pair xmap_param; + typedef std::map xmap; + typedef xmap::iterator xmap_itr; + + xmap _map; + smutex _mutex; + std::vector _pfid_txn_cnt; + const txn_data_list _empty_data_list; + + public: + txn_map(); + virtual ~txn_map(); + + void set_num_jfiles(const u_int16_t num_jfiles); + u_int32_t get_txn_pfid_cnt(const u_int16_t pfid) const; + bool insert_txn_data(const std::string& xid, const txn_data& td); + const txn_data_list get_tdata_list(const std::string& xid); + const txn_data_list get_remove_tdata_list(const std::string& xid); + bool in_map(const std::string& xid); + u_int32_t enq_cnt(); + u_int32_t deq_cnt(); + int16_t is_txn_synced(const std::string& xid); // -1=xid not found; 0=not synced; 1=synced + int16_t set_aio_compl(const std::string& xid, const u_int64_t rid); // -2=rid not found; -1=xid not found; 0=done + bool data_exists(const std::string& xid, const u_int64_t rid); + bool is_enq(const u_int64_t rid); + inline void clear() { _map.clear(); } + inline bool empty() const { return _map.empty(); } + inline size_t size() const { return _map.size(); } + void xid_list(std::vector& xv); + private: + u_int32_t cnt(const bool enq_flag); + const txn_data_list get_tdata_list_nolock(const std::string& xid); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_txn_map_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/txn_map.hpp b/cpp/src/qpid/legacystore/jrnl/txn_map.hpp deleted file mode 100644 index dab7aa76d1..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/txn_map.hpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file txn_map.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::txn_map (transaction map). - * See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_txn_map_hpp -#define mrg_journal_txn_map_hpp - -namespace mrg -{ -namespace journal -{ - class txn_map; -} -} - -#include "jrnl/smutex.hpp" -#include -#include -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \struct txn_data_struct - * \brief Struct encapsulating transaction data necessary for processing a transaction - * in the journal once it is closed with either a commit or abort. - */ - struct txn_data_struct - { - u_int64_t _rid; ///< Record id for this operation - u_int64_t _drid; ///< Dequeue record id for this operation - u_int16_t _pfid; ///< Physical file id, to be used when transferring to emap on commit - bool _enq_flag; ///< If true, enq op, otherwise deq op - bool _commit_flag; ///< (2PC transactions) Records 2PC complete c/a mode - bool _aio_compl; ///< Initially false, set to true when record AIO returns - txn_data_struct(const u_int64_t rid, const u_int64_t drid, const u_int16_t pfid, - const bool enq_flag, const bool commit_flag = false); - }; - typedef txn_data_struct txn_data; - typedef std::vector txn_data_list; - typedef txn_data_list::iterator tdl_itr; - - /** - * \class txn_map - * \brief Class for storing transaction data for each open (ie not committed or aborted) - * xid in the store. If aborted, records are discarded; if committed, they are - * transferred to the enqueue map. - * - * The data is encapsulated by struct txn_data_struct. A vector containing the information - * for each operation included as part of the same transaction is mapped against the - * xid. - * - * The aio_compl flag is set true as each AIO write operation for the enqueue or dequeue - * returns. Checking that all of these flags are true for a given xid is the mechanism - * used to determine if the transaction is syncronized (through method is_txn_synced()). - * - * On transaction commit, then each operation is handled as follows: - * - * If an enqueue (_enq_flag is true), then the rid and pfid are transferred to the enq_map. - * If a dequeue (_enq_flag is false), then the rid stored in the drid field is used to - * remove the corresponding record from the enq_map. - * - * On transaction abort, then each operation is handled as follows: - * - * If an enqueue (_enq_flag is true), then the data is simply discarded. - * If a dequeue (_enq_flag is false), then the lock for the corresponding enqueue in enq_map - * (if not a part of the same transaction) is removed, and the data discarded. - * - *
-    *   key      data
-    *
-    *   xid1 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
-    *   xid2 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
-    *   xid3 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
-    *   ...
-    * 
- */ - class txn_map - { - public: - // return/error codes - static int16_t TMAP_RID_NOT_FOUND; - static int16_t TMAP_XID_NOT_FOUND; - static int16_t TMAP_OK; - static int16_t TMAP_NOT_SYNCED; - static int16_t TMAP_SYNCED; - - private: - typedef std::pair xmap_param; - typedef std::map xmap; - typedef xmap::iterator xmap_itr; - - xmap _map; - smutex _mutex; - std::vector _pfid_txn_cnt; - const txn_data_list _empty_data_list; - - public: - txn_map(); - virtual ~txn_map(); - - void set_num_jfiles(const u_int16_t num_jfiles); - u_int32_t get_txn_pfid_cnt(const u_int16_t pfid) const; - bool insert_txn_data(const std::string& xid, const txn_data& td); - const txn_data_list get_tdata_list(const std::string& xid); - const txn_data_list get_remove_tdata_list(const std::string& xid); - bool in_map(const std::string& xid); - u_int32_t enq_cnt(); - u_int32_t deq_cnt(); - int16_t is_txn_synced(const std::string& xid); // -1=xid not found; 0=not synced; 1=synced - int16_t set_aio_compl(const std::string& xid, const u_int64_t rid); // -2=rid not found; -1=xid not found; 0=done - bool data_exists(const std::string& xid, const u_int64_t rid); - bool is_enq(const u_int64_t rid); - inline void clear() { _map.clear(); } - inline bool empty() const { return _map.empty(); } - inline size_t size() const { return _map.size(); } - void xid_list(std::vector& xv); - private: - u_int32_t cnt(const bool enq_flag); - const txn_data_list get_tdata_list_nolock(const std::string& xid); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_txn_map_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/txn_rec.h b/cpp/src/qpid/legacystore/jrnl/txn_rec.h new file mode 100644 index 0000000000..a295f56612 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/txn_rec.h @@ -0,0 +1,101 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file txn_rec.hpp + * + * Qpid asynchronous store plugin library + * + * This file contains the code for the mrg::journal::txn_rec (journal data + * record) class. See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_txn_rec_hpp +#define mrg_journal_txn_rec_hpp + +namespace mrg +{ +namespace journal +{ +class txn_rec; +} +} + +#include +#include "jrnl/jrec.hpp" +#include "jrnl/txn_hdr.hpp" + +namespace mrg +{ +namespace journal +{ + + /** + * \class txn_rec + * \brief Class to handle a single journal DTX commit or abort record. + */ + class txn_rec : public jrec + { + private: + txn_hdr _txn_hdr; ///< transaction header + const void* _xidp; ///< xid pointer for encoding (writing to disk) + void* _buff; ///< Pointer to buffer to receive data read from disk + rec_tail _txn_tail; ///< Record tail + + public: + // constructor used for read operations and xid must have memory allocated + txn_rec(); + // constructor used for write operations, where xid already exists + txn_rec(const u_int32_t magic, const u_int64_t rid, const void* const xidp, + const std::size_t xidlen, const bool owi); + virtual ~txn_rec(); + + // Prepare instance for use in reading data from journal + void reset(const u_int32_t magic); + // Prepare instance for use in writing data to journal + void reset(const u_int32_t magic, const u_int64_t rid, const void* const xidp, + const std::size_t xidlen, const bool owi); + u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks); + u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, + u_int32_t max_size_dblks); + // Decode used for recover + bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs); + + std::size_t get_xid(void** const xidpp); + std::string& str(std::string& str) const; + inline std::size_t data_size() const { return 0; } // This record never carries data + std::size_t xid_size() const; + std::size_t rec_size() const; + inline u_int64_t rid() const { return _txn_hdr._rid; } + + private: + void chk_hdr() const; + void chk_hdr(u_int64_t rid) const; + void chk_tail() const; + virtual void clean(); + }; // class txn_rec + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_txn_rec_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/txn_rec.hpp b/cpp/src/qpid/legacystore/jrnl/txn_rec.hpp deleted file mode 100644 index a295f56612..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/txn_rec.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file txn_rec.hpp - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::txn_rec (journal data - * record) class. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_txn_rec_hpp -#define mrg_journal_txn_rec_hpp - -namespace mrg -{ -namespace journal -{ -class txn_rec; -} -} - -#include -#include "jrnl/jrec.hpp" -#include "jrnl/txn_hdr.hpp" - -namespace mrg -{ -namespace journal -{ - - /** - * \class txn_rec - * \brief Class to handle a single journal DTX commit or abort record. - */ - class txn_rec : public jrec - { - private: - txn_hdr _txn_hdr; ///< transaction header - const void* _xidp; ///< xid pointer for encoding (writing to disk) - void* _buff; ///< Pointer to buffer to receive data read from disk - rec_tail _txn_tail; ///< Record tail - - public: - // constructor used for read operations and xid must have memory allocated - txn_rec(); - // constructor used for write operations, where xid already exists - txn_rec(const u_int32_t magic, const u_int64_t rid, const void* const xidp, - const std::size_t xidlen, const bool owi); - virtual ~txn_rec(); - - // Prepare instance for use in reading data from journal - void reset(const u_int32_t magic); - // Prepare instance for use in writing data to journal - void reset(const u_int32_t magic, const u_int64_t rid, const void* const xidp, - const std::size_t xidlen, const bool owi); - u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks); - u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks); - // Decode used for recover - bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs); - - std::size_t get_xid(void** const xidpp); - std::string& str(std::string& str) const; - inline std::size_t data_size() const { return 0; } // This record never carries data - std::size_t xid_size() const; - std::size_t rec_size() const; - inline u_int64_t rid() const { return _txn_hdr._rid; } - - private: - void chk_hdr() const; - void chk_hdr(u_int64_t rid) const; - void chk_tail() const; - virtual void clean(); - }; // class txn_rec - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_txn_rec_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/wmgr.h b/cpp/src/qpid/legacystore/jrnl/wmgr.h new file mode 100644 index 0000000000..8496f091e6 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/wmgr.h @@ -0,0 +1,147 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file wmgr.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::wmgr (read manager). See + * class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_wmgr_hpp +#define mrg_journal_wmgr_hpp + +namespace mrg +{ +namespace journal +{ +class wmgr; +} +} + +#include +#include "jrnl/enums.hpp" +#include "jrnl/pmgr.hpp" +#include "jrnl/wrfc.hpp" +#include + +namespace mrg +{ +namespace journal +{ + + /** + * \brief Class for managing a write page cache of arbitrary size and number of pages. + * + * The write page cache works on the principle of caching the write data within a page until + * that page is either full or flushed; this initiates a single AIO write operation to store + * the data on disk. + * + * The maximum disk throughput is achieved by keeping the write operations of uniform size. + * Waiting for a page cache to fill achieves this; and in high data volume/throughput situations + * achieves the optimal disk throughput. Calling flush() forces a write of the current page cache + * no matter how full it is, and disrupts the uniformity of the write operations. This should + * normally only be done if throughput drops and there is a danger of a page of unwritten data + * waiting around for excessive time. + * + * The usual tradeoff between data storage latency and throughput performance applies. + */ + class wmgr : public pmgr + { + private: + wrfc& _wrfc; ///< Ref to write rotating file controller + u_int32_t _max_dtokpp; ///< Max data writes per page + u_int32_t _max_io_wait_us; ///< Max wait in microseconds till submit + void* _fhdr_base_ptr; ///< Base pointer to file header memory + void** _fhdr_ptr_arr; ///< Array of pointers to file headers memory + aio_cb** _fhdr_aio_cb_arr; ///< Array of iocb pointers for file header writes + u_int32_t _cached_offset_dblks; ///< Amount of unwritten data in page (dblocks) + std::deque _ddtokl; ///< Deferred dequeue data_tok list + u_int32_t _jfsize_dblks; ///< Journal file size in dblks (NOT sblks!) + u_int32_t _jfsize_pgs; ///< Journal file size in cache pages + u_int16_t _num_jfiles; ///< Number of files used in iocb mallocs + + // TODO: Convert _enq_busy etc into a proper threadsafe lock + // TODO: Convert to enum? Are these encodes mutually exclusive? + bool _enq_busy; ///< Flag true if enqueue is in progress + bool _deq_busy; ///< Flag true if dequeue is in progress + bool _abort_busy; ///< Flag true if abort is in progress + bool _commit_busy; ///< Flag true if commit is in progress + + enum _op_type { WMGR_ENQUEUE = 0, WMGR_DEQUEUE, WMGR_ABORT, WMGR_COMMIT }; + static const char* _op_str[]; + + enq_rec _enq_rec; ///< Enqueue record used for encoding/decoding + deq_rec _deq_rec; ///< Dequeue record used for encoding/decoding + txn_rec _txn_rec; ///< Transaction record used for encoding/decoding + std::set _txn_pending_set; ///< Set containing xids of pending commits/aborts + + public: + wmgr(jcntl* jc, enq_map& emap, txn_map& tmap, wrfc& wrfc); + wmgr(jcntl* jc, enq_map& emap, txn_map& tmap, wrfc& wrfc, const u_int32_t max_dtokpp, + const u_int32_t max_iowait_us); + virtual ~wmgr(); + + void initialize(aio_callback* const cbp, const u_int32_t wcache_pgsize_sblks, + const u_int16_t wcache_num_pages, const u_int32_t max_dtokpp, + const u_int32_t max_iowait_us, std::size_t eo = 0); + iores enqueue(const void* const data_buff, const std::size_t tot_data_len, + const std::size_t this_data_len, data_tok* dtokp, const void* const xid_ptr, + const std::size_t xid_len, const bool transient, const bool external); + iores dequeue(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len, + const bool txn_coml_commit); + iores abort(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len); + iores commit(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len); + iores flush(); + int32_t get_events(page_state state, timespec* const timeout, bool flush = false); + bool is_txn_synced(const std::string& xid); + inline bool curr_pg_blocked() const { return _page_cb_arr[_pg_index]._state != UNUSED; } + inline bool curr_file_blocked() const { return _wrfc.aio_cnt() > 0; } + inline u_int32_t unflushed_dblks() { return _cached_offset_dblks; } + + // Debug aid + const std::string status_str() const; + + private: + void initialize(aio_callback* const cbp, const u_int32_t wcache_pgsize_sblks, + const u_int16_t wcache_num_pages); + iores pre_write_check(const _op_type op, const data_tok* const dtokp, + const std::size_t xidsize = 0, const std::size_t dsize = 0, const bool external = false) + const; + void dequeue_check(const std::string& xid, const u_int64_t drid); + void file_header_check(const u_int64_t rid, const bool cont, const u_int32_t rec_dblks_rem); + void flush_check(iores& res, bool& cont, bool& done); + iores write_flush(); + iores rotate_file(); + void dblk_roundup(); + void write_fhdr(u_int64_t rid, u_int16_t fid, u_int16_t lid, std::size_t fro); + void rotate_page(); + void clean(); + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_wmgr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/wmgr.hpp b/cpp/src/qpid/legacystore/jrnl/wmgr.hpp deleted file mode 100644 index 8496f091e6..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/wmgr.hpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file wmgr.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::wmgr (read manager). See - * class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_wmgr_hpp -#define mrg_journal_wmgr_hpp - -namespace mrg -{ -namespace journal -{ -class wmgr; -} -} - -#include -#include "jrnl/enums.hpp" -#include "jrnl/pmgr.hpp" -#include "jrnl/wrfc.hpp" -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \brief Class for managing a write page cache of arbitrary size and number of pages. - * - * The write page cache works on the principle of caching the write data within a page until - * that page is either full or flushed; this initiates a single AIO write operation to store - * the data on disk. - * - * The maximum disk throughput is achieved by keeping the write operations of uniform size. - * Waiting for a page cache to fill achieves this; and in high data volume/throughput situations - * achieves the optimal disk throughput. Calling flush() forces a write of the current page cache - * no matter how full it is, and disrupts the uniformity of the write operations. This should - * normally only be done if throughput drops and there is a danger of a page of unwritten data - * waiting around for excessive time. - * - * The usual tradeoff between data storage latency and throughput performance applies. - */ - class wmgr : public pmgr - { - private: - wrfc& _wrfc; ///< Ref to write rotating file controller - u_int32_t _max_dtokpp; ///< Max data writes per page - u_int32_t _max_io_wait_us; ///< Max wait in microseconds till submit - void* _fhdr_base_ptr; ///< Base pointer to file header memory - void** _fhdr_ptr_arr; ///< Array of pointers to file headers memory - aio_cb** _fhdr_aio_cb_arr; ///< Array of iocb pointers for file header writes - u_int32_t _cached_offset_dblks; ///< Amount of unwritten data in page (dblocks) - std::deque _ddtokl; ///< Deferred dequeue data_tok list - u_int32_t _jfsize_dblks; ///< Journal file size in dblks (NOT sblks!) - u_int32_t _jfsize_pgs; ///< Journal file size in cache pages - u_int16_t _num_jfiles; ///< Number of files used in iocb mallocs - - // TODO: Convert _enq_busy etc into a proper threadsafe lock - // TODO: Convert to enum? Are these encodes mutually exclusive? - bool _enq_busy; ///< Flag true if enqueue is in progress - bool _deq_busy; ///< Flag true if dequeue is in progress - bool _abort_busy; ///< Flag true if abort is in progress - bool _commit_busy; ///< Flag true if commit is in progress - - enum _op_type { WMGR_ENQUEUE = 0, WMGR_DEQUEUE, WMGR_ABORT, WMGR_COMMIT }; - static const char* _op_str[]; - - enq_rec _enq_rec; ///< Enqueue record used for encoding/decoding - deq_rec _deq_rec; ///< Dequeue record used for encoding/decoding - txn_rec _txn_rec; ///< Transaction record used for encoding/decoding - std::set _txn_pending_set; ///< Set containing xids of pending commits/aborts - - public: - wmgr(jcntl* jc, enq_map& emap, txn_map& tmap, wrfc& wrfc); - wmgr(jcntl* jc, enq_map& emap, txn_map& tmap, wrfc& wrfc, const u_int32_t max_dtokpp, - const u_int32_t max_iowait_us); - virtual ~wmgr(); - - void initialize(aio_callback* const cbp, const u_int32_t wcache_pgsize_sblks, - const u_int16_t wcache_num_pages, const u_int32_t max_dtokpp, - const u_int32_t max_iowait_us, std::size_t eo = 0); - iores enqueue(const void* const data_buff, const std::size_t tot_data_len, - const std::size_t this_data_len, data_tok* dtokp, const void* const xid_ptr, - const std::size_t xid_len, const bool transient, const bool external); - iores dequeue(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len, - const bool txn_coml_commit); - iores abort(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len); - iores commit(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len); - iores flush(); - int32_t get_events(page_state state, timespec* const timeout, bool flush = false); - bool is_txn_synced(const std::string& xid); - inline bool curr_pg_blocked() const { return _page_cb_arr[_pg_index]._state != UNUSED; } - inline bool curr_file_blocked() const { return _wrfc.aio_cnt() > 0; } - inline u_int32_t unflushed_dblks() { return _cached_offset_dblks; } - - // Debug aid - const std::string status_str() const; - - private: - void initialize(aio_callback* const cbp, const u_int32_t wcache_pgsize_sblks, - const u_int16_t wcache_num_pages); - iores pre_write_check(const _op_type op, const data_tok* const dtokp, - const std::size_t xidsize = 0, const std::size_t dsize = 0, const bool external = false) - const; - void dequeue_check(const std::string& xid, const u_int64_t drid); - void file_header_check(const u_int64_t rid, const bool cont, const u_int32_t rec_dblks_rem); - void flush_check(iores& res, bool& cont, bool& done); - iores write_flush(); - iores rotate_file(); - void dblk_roundup(); - void write_fhdr(u_int64_t rid, u_int16_t fid, u_int16_t lid, std::size_t fro); - void rotate_page(); - void clean(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_wmgr_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/wrfc.h b/cpp/src/qpid/legacystore/jrnl/wrfc.h new file mode 100644 index 0000000000..f71eb4f317 --- /dev/null +++ b/cpp/src/qpid/legacystore/jrnl/wrfc.h @@ -0,0 +1,154 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * \file wrfc.hpp + * + * Qpid asynchronous store plugin library + * + * File containing code for class mrg::journal::wrfc (write rotating + * file controller). See class documentation for details. + * + * \author Kim van der Riet + */ + +#ifndef mrg_journal_wrfc_hpp +#define mrg_journal_wrfc_hpp + +namespace mrg +{ +namespace journal +{ +class wrfc; +} +} + +#include +#include "jrnl/enums.hpp" +#include "jrnl/rrfc.hpp" + +namespace mrg +{ +namespace journal +{ + + /** + * \class wrfc + * \brief Class to handle write management of a journal rotating file controller. + */ + class wrfc : public rfc + { + private: + u_int32_t _fsize_sblks; ///< Size of journal files in sblks + u_int32_t _fsize_dblks; ///< Size of journal files in dblks + u_int32_t _enq_cap_offs_dblks; ///< Enqueue capacity offset + u_int64_t _rid; ///< Master counter for record ID (rid) + bool _reset_ok; ///< Flag set when reset succeeds + bool _owi; ///< Overwrite indicator + bool _frot; ///< Flag is true for first rotation, false otherwise + + public: + wrfc(const lpmgr* lpmp); + virtual ~wrfc(); + + /** + * \brief Initialize the controller. + * \param fsize_sblks Size of each journal file in sblks. + * \param rdp Struct carrying restore information. Optional for non-restore use, defaults to 0 (NULL). + */ + using rfc::initialize; + void initialize(const u_int32_t fsize_sblks, rcvdat* rdp = 0); + + /** + * \brief Rotate active file controller to next file in rotating file group. + * \exception jerrno::JERR__NINIT if called before calling initialize(). + */ + iores rotate(); + + /** + * \brief Returns the index of the earliest complete file within the rotating + * file group. Unwritten files are excluded. The currently active file is + * excluded unless it is the only written file. + */ + u_int16_t earliest_index() const; + + /** + * \brief Determines if a proposed write would cause the enqueue threshold to be exceeded. + * + * The following routine finds whether the next write will take the write pointer to beyond the + * enqueue limit threshold. The following illustrates how this is achieved. + *
+        * Current file index: 4                         +---+----------+
+        * X's mark still-enqueued records               |msg| 1-thresh |
+        * msg = current msg size + unwritten cache      +---+----------+
+        * thresh = JRNL_ENQ_THRESHOLD as a fraction     ^              V
+        *            +-------+-------+-------+-------+--+----+-------+-+-----+-------+
+        * file num ->|   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7   |
+        * enq recs ->| X  XX |XX XXX |XX XXXX|XXXXXXX|XX     |       |       |     X |
+        *            +-------+-------+-------+-------+--+----+-------+-+-----+-------+
+        *                                               ^        ^       ^
+        *                                  subm_dblks --+        |       |
+        *                                                      These files must be free of enqueues
+        *                                                      If not, return true.
+        * 
+ * \param enq_dsize_dblks Proposed size of write in dblocks + */ + bool enq_threshold(const u_int32_t enq_dsize_dblks) const; + + inline u_int64_t rid() const { return _rid; } + inline u_int64_t get_incr_rid() { return _rid++; } + bool wr_reset(); + inline bool is_wr_reset() const { return _reset_ok; } + inline bool owi() const { return _owi; } + inline bool frot() const { return _frot; } + + // Convenience access methods to current file controller + + inline int fh() const { return _curr_fc->wr_fh(); } + + inline u_int32_t subm_cnt_dblks() const { return _curr_fc->wr_subm_cnt_dblks(); } + inline std::size_t subm_offs() const { return _curr_fc->wr_subm_offs(); } + inline u_int32_t add_subm_cnt_dblks(u_int32_t a) { return _curr_fc->add_wr_subm_cnt_dblks(a); } + + inline u_int32_t cmpl_cnt_dblks() const { return _curr_fc->wr_cmpl_cnt_dblks(); } + inline std::size_t cmpl_offs() const { return _curr_fc->wr_cmpl_offs(); } + inline u_int32_t add_cmpl_cnt_dblks(u_int32_t a) { return _curr_fc->add_wr_cmpl_cnt_dblks(a); } + + inline u_int16_t aio_cnt() const { return _curr_fc->aio_cnt(); } + inline u_int16_t incr_aio_cnt() { return _curr_fc->incr_aio_cnt(); } + inline u_int16_t decr_aio_cnt() { return _curr_fc->decr_aio_cnt(); } + + inline bool is_void() const { return _curr_fc->wr_void(); } + inline bool is_empty() const { return _curr_fc->wr_empty(); } + inline u_int32_t remaining_dblks() const { return _curr_fc->wr_remaining_dblks(); } + inline bool is_full() const { return _curr_fc->is_wr_full(); }; + inline bool is_compl() const { return _curr_fc->is_wr_compl(); }; + inline u_int32_t aio_outstanding_dblks() const { return _curr_fc->wr_aio_outstanding_dblks(); } + inline bool file_rotate() const { return _curr_fc->wr_file_rotate(); } + + // Debug aid + std::string status_str() const; + }; + +} // namespace journal +} // namespace mrg + +#endif // ifndef mrg_journal_wrfc_hpp diff --git a/cpp/src/qpid/legacystore/jrnl/wrfc.hpp b/cpp/src/qpid/legacystore/jrnl/wrfc.hpp deleted file mode 100644 index f71eb4f317..0000000000 --- a/cpp/src/qpid/legacystore/jrnl/wrfc.hpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file wrfc.hpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::wrfc (write rotating - * file controller). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef mrg_journal_wrfc_hpp -#define mrg_journal_wrfc_hpp - -namespace mrg -{ -namespace journal -{ -class wrfc; -} -} - -#include -#include "jrnl/enums.hpp" -#include "jrnl/rrfc.hpp" - -namespace mrg -{ -namespace journal -{ - - /** - * \class wrfc - * \brief Class to handle write management of a journal rotating file controller. - */ - class wrfc : public rfc - { - private: - u_int32_t _fsize_sblks; ///< Size of journal files in sblks - u_int32_t _fsize_dblks; ///< Size of journal files in dblks - u_int32_t _enq_cap_offs_dblks; ///< Enqueue capacity offset - u_int64_t _rid; ///< Master counter for record ID (rid) - bool _reset_ok; ///< Flag set when reset succeeds - bool _owi; ///< Overwrite indicator - bool _frot; ///< Flag is true for first rotation, false otherwise - - public: - wrfc(const lpmgr* lpmp); - virtual ~wrfc(); - - /** - * \brief Initialize the controller. - * \param fsize_sblks Size of each journal file in sblks. - * \param rdp Struct carrying restore information. Optional for non-restore use, defaults to 0 (NULL). - */ - using rfc::initialize; - void initialize(const u_int32_t fsize_sblks, rcvdat* rdp = 0); - - /** - * \brief Rotate active file controller to next file in rotating file group. - * \exception jerrno::JERR__NINIT if called before calling initialize(). - */ - iores rotate(); - - /** - * \brief Returns the index of the earliest complete file within the rotating - * file group. Unwritten files are excluded. The currently active file is - * excluded unless it is the only written file. - */ - u_int16_t earliest_index() const; - - /** - * \brief Determines if a proposed write would cause the enqueue threshold to be exceeded. - * - * The following routine finds whether the next write will take the write pointer to beyond the - * enqueue limit threshold. The following illustrates how this is achieved. - *
-        * Current file index: 4                         +---+----------+
-        * X's mark still-enqueued records               |msg| 1-thresh |
-        * msg = current msg size + unwritten cache      +---+----------+
-        * thresh = JRNL_ENQ_THRESHOLD as a fraction     ^              V
-        *            +-------+-------+-------+-------+--+----+-------+-+-----+-------+
-        * file num ->|   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7   |
-        * enq recs ->| X  XX |XX XXX |XX XXXX|XXXXXXX|XX     |       |       |     X |
-        *            +-------+-------+-------+-------+--+----+-------+-+-----+-------+
-        *                                               ^        ^       ^
-        *                                  subm_dblks --+        |       |
-        *                                                      These files must be free of enqueues
-        *                                                      If not, return true.
-        * 
- * \param enq_dsize_dblks Proposed size of write in dblocks - */ - bool enq_threshold(const u_int32_t enq_dsize_dblks) const; - - inline u_int64_t rid() const { return _rid; } - inline u_int64_t get_incr_rid() { return _rid++; } - bool wr_reset(); - inline bool is_wr_reset() const { return _reset_ok; } - inline bool owi() const { return _owi; } - inline bool frot() const { return _frot; } - - // Convenience access methods to current file controller - - inline int fh() const { return _curr_fc->wr_fh(); } - - inline u_int32_t subm_cnt_dblks() const { return _curr_fc->wr_subm_cnt_dblks(); } - inline std::size_t subm_offs() const { return _curr_fc->wr_subm_offs(); } - inline u_int32_t add_subm_cnt_dblks(u_int32_t a) { return _curr_fc->add_wr_subm_cnt_dblks(a); } - - inline u_int32_t cmpl_cnt_dblks() const { return _curr_fc->wr_cmpl_cnt_dblks(); } - inline std::size_t cmpl_offs() const { return _curr_fc->wr_cmpl_offs(); } - inline u_int32_t add_cmpl_cnt_dblks(u_int32_t a) { return _curr_fc->add_wr_cmpl_cnt_dblks(a); } - - inline u_int16_t aio_cnt() const { return _curr_fc->aio_cnt(); } - inline u_int16_t incr_aio_cnt() { return _curr_fc->incr_aio_cnt(); } - inline u_int16_t decr_aio_cnt() { return _curr_fc->decr_aio_cnt(); } - - inline bool is_void() const { return _curr_fc->wr_void(); } - inline bool is_empty() const { return _curr_fc->wr_empty(); } - inline u_int32_t remaining_dblks() const { return _curr_fc->wr_remaining_dblks(); } - inline bool is_full() const { return _curr_fc->is_wr_full(); }; - inline bool is_compl() const { return _curr_fc->is_wr_compl(); }; - inline u_int32_t aio_outstanding_dblks() const { return _curr_fc->wr_aio_outstanding_dblks(); } - inline bool file_rotate() const { return _curr_fc->wr_file_rotate(); } - - // Debug aid - std::string status_str() const; - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef mrg_journal_wrfc_hpp -- cgit v1.2.1