/* * * 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.h * * 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 QPID_LEGACYSTORE_JRNL_JREC_H #define QPID_LEGACYSTORE_JRNL_JREC_H namespace mrg { namespace journal { class jrec; } } #include #include #include "qpid/legacystore/jrnl/rec_hdr.h" #include "qpid/legacystore/jrnl/rec_tail.h" #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 QPID_LEGACYSTORE_JRNL_JREC_H