summaryrefslogtreecommitdiff
path: root/src/md/inc/recordpool.h
blob: 36bd67a656de0a79c52a16e87e1dc3a6129255e3 (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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//*****************************************************************************
// RecordPool.h -- header file for record heaps.
// 

//
//*****************************************************************************
#ifndef _RECORDPOOL_H_
#define _RECORDPOOL_H_

#if _MSC_VER >= 1100
#pragma once
#endif

#include <stgpool.h>

//*****************************************************************************
// This Record pool class collects user Records into a big consecutive heap.
// The list of Records is kept in memory while adding, and
// finally flushed to a stream at the caller's request.
//*****************************************************************************
class RecordPool : public StgPool
{
    friend class VerifyLayoutsMD;

    using StgPool::InitNew;
    using StgPool::InitOnMem;

public:
    RecordPool() :
        StgPool(1024, 1)
    { }

//*****************************************************************************
// Init the pool for use.  This is called for the create empty case.
//*****************************************************************************
    __checkReturn 
    HRESULT InitNew(
        UINT32 cbRec,                    // Record size.
        UINT32 cRecsInit);                // Initial guess of count of record.
    
//*****************************************************************************
// Load a Record heap from persisted memory.  If a copy of the data is made
// (so that it may be updated), then a new hash table is generated which can
// be used to elminate duplicates with new Records.
//*****************************************************************************
    __checkReturn 
    HRESULT InitOnMem(
        ULONG cbRec,            // Record size.
        void *pData,            // Predefined data.
        ULONG iSize,            // Size of data.
        BOOL  fReadOnly);       // true if append is forbidden.

//*****************************************************************************
// Allocate memory if we don't have any, or grow what we have.  If successful,
// then at least iRequired bytes will be allocated.
//*****************************************************************************
    bool Grow(                                // true if successful.
        ULONG        iRequired);                // Min required bytes to allocate.

//*****************************************************************************
// The Record will be added to the pool.  The index of the Record in the pool
// is returned in *piIndex.  If the Record is already in the pool, then the
// index will be to the existing copy of the Record.
//*****************************************************************************
    HRESULT AddRecord(
        BYTE  **ppRecord, 
        UINT32 *pnIndex);       // Return 1-based index of Record here.
    
//*****************************************************************************
// Insert a Record into the pool.  The index of the Record before which to
// insert is specified.  Shifts all records down.  Return a pointer to the
// new record.
//*****************************************************************************
    HRESULT InsertRecord(
        UINT32 nIndex,          // [IN] Insert record before this.
        BYTE **ppRecord);
    
//*****************************************************************************
// Return a pointer to a Record given an index previously handed out by
// AddRecord or FindRecord.
//*****************************************************************************
    __checkReturn 
    virtual HRESULT GetRecord(
        UINT32 nIndex,            // 1-based index of Record in pool.
        BYTE **ppRecord);
    
//*****************************************************************************
// Given a pointer to a record, determine the index corresponding to the
// record.
//*****************************************************************************
    virtual ULONG GetIndexForRecord(        // 1-based index of Record in pool.
        const void *pRecord);                // Pointer to Record in pool.

//*****************************************************************************
// Given a purported pointer to a record, determine if the pointer is valid.
//*****************************************************************************
    virtual int IsValidPointerForRecord(    // true or false.
        const void *pRecord);                // Pointer to Record in pool.

//*****************************************************************************
// How many objects are there in the pool?  If the count is 0, you don't need
// to persist anything at all to disk.
//*****************************************************************************
    UINT32 Count()
    { return GetNextOffset() / m_cbRec; }

//*****************************************************************************
// Indicate if heap is empty.  This has to be based on the size of the data
// we are keeping.  If you open in r/o mode on memory, there is no hash
// table.
//*****************************************************************************
    virtual int IsEmpty()                    // true if empty.
    { return (GetNextOffset() == 0); }

//*****************************************************************************
// Is the index valid for the Record?
//*****************************************************************************
    virtual int IsValidCookie(ULONG ulCookie)
    { return (ulCookie == 0 || IsValidOffset((ulCookie-1) * m_cbRec)); }

//*****************************************************************************
// Return the size of the heap.
//*****************************************************************************
    ULONG GetNextIndex()
    { return (GetNextOffset() / m_cbRec); }

//*****************************************************************************
// Replace the contents of this pool with those from another pool.  The other
//    pool loses ownership of the memory.
//*****************************************************************************
    __checkReturn 
    HRESULT ReplaceContents(
        RecordPool *pOther);                // The other record pool.

//*****************************************************************************
// Return the first record in a pool, and set up a context for fast
//  iterating through the pool.  Note that this scheme does pretty minimal
//  error checking.
//*****************************************************************************
    void *GetFirstRecord(                    // Pointer to Record in pool.
        void        **pContext);            // Store context here.

//*****************************************************************************
// Given a pointer to a record, return a pointer to the next record.
//  Note that this scheme does pretty minimal error checking. In particular,
//  this will let the caller walk off of the end of valid data in the last
//  segment.
//*****************************************************************************
    void *GetNextRecord(                    // Pointer to Record in pool.
        void        *pRecord,                // Current record.
        void        **pContext);            // Stored context here.
    
private:
    UINT32 m_cbRec;                // How large is each record?
    
};  // class RecordPool

#endif // _RECORDPOOL_H_