blob: 9d0771cabd1c1b0059646ef3381b8f512e73c701 [file] [log] [blame]
/*
*
* 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 <cstddef>
#include <fstream>
#include "qpid/legacystore/jrnl/rec_hdr.h"
#include "qpid/legacystore/jrnl/rec_tail.h"
#include <string>
#include <sys/types.h>
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.
*
* <b>Example:</b> 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:
* <pre>
* |<---ps--->|
* +----------+----------+----------+----...
* | |r2a| r2b | r2c | |
* |<-r1-><----------r2----------> |
* +----------+----------+----------+----...
* page: p0 p1 p2
* </pre>
* 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:
* <pre>
* 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)
* </pre>
*
* \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