root/trunk/whisperlib/common/io/logio/recordio.h

Revision 7, 5.3 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Catalin Popescu
31
32 // This contains utilities for reading and writing records to / from
33 // a stream.
34 //
35 // The main idea is that we add pieces of information (memory stream data)
36 // to a record stream. We add these in blocks of fixed size (so in case of
37 // corrupted blocks we can skip them). Records may spawn over multiple blocks.
38 //
39 // The reading part builds pieces of file (block_size) and from there extracts
40 // records.
41 //
42 // Is needless to say that in order to work, the reader should be created
43 // with the same record size as the writer.
44 //
45
46 #ifndef __COMMON_IO_LOGIO_RECORDIO_H__
47 #define __COMMON_IO_LOGIO_RECORDIO_H__
48
49 #include <zlib.h>
50 #include <whisperlib/common/io/buffer/memory_stream.h>
51 #include <whisperlib/common/io/zlib/zlibwrapper.h>
52
53 namespace io {
54
55 static const int32 kDefaultRecordBlockSize = 65536;
56 static const int32 kMaximumRecordBlockSize = 0xFFFFFF;
57
58 class RecordWriter {
59  public:
60   enum {
61     HAS_CONT  = 1,
62     IS_ZIPPED = 2,
63   };
64
65   RecordWriter(int32 block_size = kDefaultRecordBlockSize,
66                bool deflate = false,
67                float dumpable_percent = .9);
68   ~RecordWriter();
69
70   // Appends the provided content from in to the record.
71   // Upon a return of true, the value of 'out' is ready to
72   // be appended to the file as a one shot-write.
73   bool AppendRecord(io::MemoryStream* in, io::MemoryStream* out) {
74     return AppendRecord(in, out, false);
75   }
76   bool AppendRecord(const char* buffer, int32 size, io::MemoryStream* out);
77
78   // This returns the current content (accumulated so far) as a one block
79   // to be written to the disk.
80   void FinalizeContent(io::MemoryStream* out);
81
82   // In a block we can have at most this much data from a record
83   // We prepend the record size
84   int32 max_block_record_size() const {
85     return block_size_ - kTrailerEnd - sizeof(int32);
86   }
87
88   int32 leftover() const {
89     return content_.Size();
90   }
91  private:
92   bool AppendRecord(io::MemoryStream* in, io::MemoryStream* out,
93                     bool is_zipped);
94   // We trail with the content size and crc..
95   static const int32 kTrailerEnd = sizeof(int32) + sizeof(int32);
96
97   const int32 block_size_;     // we write record blocks of this size
98   const int32 dumpable_size_;  // we can finish a record if we have more
99                                // than this in the buffer and the next
100                                // records overflows
101   io::MemoryStream content_;   // accumulated content so far..
102   char* const padding_;        // just some zeroes used for padding
103   ZlibDeflateWrapper* zlib_;   // for compressing content
104   io::MemoryStream zlib_content_;
105                                // buffer of compressed content
106
107   DISALLOW_EVIL_CONSTRUCTORS(RecordWriter);
108 };
109
110 class RecordReader {
111  public:
112   explicit RecordReader(int32 block_size = kDefaultRecordBlockSize);
113   ~RecordReader();
114
115   // Reads the content of the next record from the provided memory stream
116   enum ReadResult {
117     READ_OK = 0,         // out contains some valid data
118     READ_NO_DATA,        // there is not enough data in 'in' to be read
119     READ_CRC_CORRUPTED,  // the data was corrupted (crc wise)
120     READ_ZIP_CORRUPTED,  // the zipped recored was corrupted
121   };
122   ReadResult ReadRecord(io::MemoryStream* in, io::MemoryStream* out);
123   void Clear() {
124     temp_.Clear();
125     content_.Clear();
126   }
127  private:
128   RecordReader::ReadResult ReadNextBlock(io::MemoryStream* in);
129
130   static const int32 kTrailerEnd = sizeof(int32) + sizeof(int32);
131
132   const int32 block_size_;    // we write records of this size
133   io::MemoryStream temp_;     // a temp buffer
134   io::MemoryStream content_;  // accumulated content so far..
135   io::MemoryStream zip_content_;
136                               // zipped accumulated content so far..
137   ZlibInflateWrapper zlib_;   // inflates stuff for us
138
139   DISALLOW_EVIL_CONSTRUCTORS(RecordReader);
140 };
141 }
142
143 #endif  // __COMMON_IO_LOGIO_RECORDIO_H__
Note: See TracBrowser for help on using the browser.