1 | /* |
2 | * The contents of this file are subject to the Initial |
3 | * Developer's Public License Version 1.0 (the "License"); |
4 | * you may not use this file except in compliance with the |
5 | * License. You may obtain a copy of the License at |
6 | * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. |
7 | * |
8 | * Software distributed under the License is distributed AS IS, |
9 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. |
10 | * See the License for the specific language governing rights |
11 | * and limitations under the License. |
12 | * |
13 | * The Original Code was created by Dmitry Yemanov |
14 | * for the Firebird Open Source RDBMS project. |
15 | * |
16 | * Copyright (c) 2006 Dmitry Yemanov <dimitr@users.sf.net> |
17 | * and all contributors signed below. |
18 | * |
19 | * All Rights Reserved. |
20 | * Contributor(s): ______________________________________. |
21 | */ |
22 | |
23 | #ifndef JRD_TEMP_SPACE_H |
24 | #define JRD_TEMP_SPACE_H |
25 | |
26 | #include "firebird.h" |
27 | #include "../common/classes/fb_string.h" |
28 | #include "../common/classes/array.h" |
29 | #include "../common/classes/TempFile.h" |
30 | #include "../common/config/dir_list.h" |
31 | #include "../common/classes/init.h" |
32 | #include "../common/classes/tree.h" |
33 | |
34 | class TempSpace : public Firebird::File |
35 | { |
36 | public: |
37 | TempSpace(MemoryPool& pool, const Firebird::PathName& prefix, bool dynamic = true); |
38 | virtual ~TempSpace(); |
39 | |
40 | size_t read(offset_t offset, void* buffer, size_t length); |
41 | size_t write(offset_t offset, const void* buffer, size_t length); |
42 | |
43 | void unlink() {} |
44 | |
45 | offset_t getSize() const |
46 | { |
47 | return logicalSize; |
48 | } |
49 | |
50 | void extend(size_t size); |
51 | |
52 | offset_t allocateSpace(size_t size); |
53 | void releaseSpace(offset_t offset, size_t size); |
54 | |
55 | UCHAR* inMemory(offset_t offset, size_t size) const; |
56 | |
57 | struct SegmentInMemory |
58 | { |
59 | UCHAR* memory; |
60 | offset_t position; |
61 | size_t size; |
62 | }; |
63 | |
64 | typedef Firebird::Array<SegmentInMemory> Segments; |
65 | |
66 | size_t allocateBatch(size_t count, size_t minSize, size_t maxSize, Segments& segments); |
67 | |
68 | bool validate(offset_t& freeSize) const; |
69 | private: |
70 | |
71 | // Generic space block |
72 | class Block |
73 | { |
74 | public: |
75 | Block(Block* tail, size_t length) |
76 | : next(NULL), size(length) |
77 | { |
78 | if (tail) |
79 | { |
80 | tail->next = this; |
81 | } |
82 | prev = tail; |
83 | } |
84 | |
85 | virtual ~Block() {} |
86 | |
87 | virtual size_t read(offset_t offset, void* buffer, size_t length) = 0; |
88 | virtual size_t write(offset_t offset, const void* buffer, size_t length) = 0; |
89 | |
90 | virtual UCHAR* inMemory(offset_t offset, size_t size) const = 0; |
91 | virtual bool sameFile(const Firebird::TempFile* file) const = 0; |
92 | |
93 | Block *prev; |
94 | Block *next; |
95 | offset_t size; |
96 | }; |
97 | |
98 | class MemoryBlock : public Block |
99 | { |
100 | public: |
101 | MemoryBlock(UCHAR* memory, Block* tail, size_t length) |
102 | : Block(tail, length), ptr(memory) |
103 | {} |
104 | |
105 | ~MemoryBlock() |
106 | { |
107 | delete[] ptr; |
108 | } |
109 | |
110 | size_t read(offset_t offset, void* buffer, size_t length); |
111 | size_t write(offset_t offset, const void* buffer, size_t length); |
112 | |
113 | UCHAR* inMemory(offset_t offset, size_t _size) const |
114 | { |
115 | if ((offset < this->size) && (offset + _size <= this->size)) |
116 | return ptr + offset; |
117 | |
118 | return NULL; |
119 | } |
120 | |
121 | bool sameFile(const Firebird::TempFile*) const |
122 | { |
123 | return false; |
124 | } |
125 | |
126 | protected: |
127 | UCHAR* ptr; |
128 | }; |
129 | |
130 | class InitialBlock : public MemoryBlock |
131 | { |
132 | public: |
133 | InitialBlock(UCHAR* memory, size_t length) |
134 | : MemoryBlock(memory, NULL, length) |
135 | {} |
136 | |
137 | ~InitialBlock() |
138 | { |
139 | ptr = NULL; |
140 | } |
141 | }; |
142 | |
143 | class FileBlock : public Block |
144 | { |
145 | public: |
146 | FileBlock(Firebird::TempFile* f, Block* tail, size_t length) |
147 | : Block(tail, length), file(f) |
148 | { |
149 | fb_assert(file); |
150 | |
151 | // FileBlock is created after file was extended by length (look at |
152 | // TempSpace::extend) so this FileBlock is already inside the file |
153 | seek = file->getSize() - length; |
154 | } |
155 | |
156 | ~FileBlock() {} |
157 | |
158 | size_t read(offset_t offset, void* buffer, size_t length); |
159 | size_t write(offset_t offset, const void* buffer, size_t length); |
160 | |
161 | UCHAR* inMemory(offset_t /*offset*/, size_t /*a_size*/) const |
162 | { |
163 | return NULL; |
164 | } |
165 | |
166 | bool sameFile(const Firebird::TempFile* aFile) const |
167 | { |
168 | return (aFile == this->file); |
169 | } |
170 | |
171 | private: |
172 | Firebird::TempFile* file; |
173 | offset_t seek; |
174 | }; |
175 | |
176 | Block* findBlock(offset_t& offset) const; |
177 | Firebird::TempFile* setupFile(size_t size); |
178 | |
179 | UCHAR* findMemory(offset_t& begin, offset_t end, size_t size) const; |
180 | |
181 | // free/used segments management |
182 | class Segment |
183 | { |
184 | public: |
185 | Segment() : position(0), size(0) |
186 | {} |
187 | |
188 | Segment(offset_t aPosition, offset_t aSize) : |
189 | position(aPosition), size(aSize) |
190 | {} |
191 | |
192 | offset_t position; |
193 | offset_t size; |
194 | |
195 | static const offset_t& generate(const void* /*sender*/, const Segment& segment) |
196 | { |
197 | return segment.position; |
198 | } |
199 | }; |
200 | |
201 | MemoryPool& pool; |
202 | Firebird::PathName filePrefix; |
203 | offset_t logicalSize; |
204 | offset_t physicalSize; |
205 | offset_t localCacheUsage; |
206 | Block* head; |
207 | Block* tail; |
208 | Firebird::Array<Firebird::TempFile*> tempFiles; |
209 | Firebird::Array<UCHAR> initialBuffer; |
210 | bool initiallyDynamic; |
211 | |
212 | typedef Firebird::BePlusTree<Segment, offset_t, MemoryPool, Segment> FreeSegmentTree; |
213 | FreeSegmentTree freeSegments; |
214 | |
215 | static Firebird::GlobalPtr<Firebird::Mutex> initMutex; |
216 | static Firebird::TempDirectoryList* tempDirs; |
217 | static size_t minBlockSize; |
218 | static offset_t globalCacheUsage; |
219 | }; |
220 | |
221 | #endif // JRD_TEMP_SPACE_H |
222 | |