summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/legacystore/jrnl/jrec.h
blob: 9d0771cabd1c1b0059646ef3381b8f512e73c701 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
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.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