Skip to content

Commit 50193eb

Browse files
Andrey KravchenkoXaBbl4
authored andcommitted
Refactor class and fix server crash
1 parent e8546bf commit 50193eb

File tree

2 files changed

+97
-88
lines changed

2 files changed

+97
-88
lines changed

src/jrd/TempSpace.cpp

Lines changed: 77 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,69 @@ FB_SIZE_T TempSpace::FileBlock::write(offset_t offset, const void* buffer, FB_SI
129129
return file->write(offset, buffer, length);
130130
}
131131

132+
//
133+
// FreeSegmentBySize class
134+
//
135+
136+
void TempSpace::FreeSegmentBySize::addSegment(Segment* const segment)
137+
{
138+
if (m_items.locate(segment->size))
139+
{
140+
SegmentsStack* const cur = &m_items.current();
141+
segment->next = nullptr;
142+
segment->prev = cur->head;
143+
cur->head->next = segment;
144+
cur->head = segment;
145+
}
146+
else
147+
{
148+
segment->prev = nullptr;
149+
segment->next = nullptr;
150+
m_items.add(SegmentsStack(segment->size, segment));
151+
}
152+
}
153+
154+
void TempSpace::FreeSegmentBySize::removeSegment(Segment* const segment)
155+
{
156+
if (segment->next == nullptr)
157+
{
158+
if (!m_items.locate(segment->size))
159+
fb_assert(false);
160+
161+
SegmentsStack* cur = &m_items.current();
162+
if (segment->prev)
163+
{
164+
segment->prev->next = nullptr;
165+
cur->head = segment->prev;
166+
segment->prev = nullptr;
167+
}
168+
else
169+
m_items.fastRemove();
170+
}
171+
else
172+
{
173+
if (segment->prev)
174+
segment->prev->next = segment->next;
175+
176+
segment->next->prev = segment->prev;
177+
178+
segment->prev = nullptr;
179+
segment->next = nullptr;
180+
}
181+
}
182+
183+
TempSpace::Segment* TempSpace::FreeSegmentBySize::getSegment(FB_SIZE_T size)
184+
{
185+
// Search through the available space in the not used segments list
186+
if (m_items.locate(locGreatEqual, size))
187+
{
188+
SegmentsStack* const cur = &m_items.current();
189+
fb_assert(cur->head);
190+
return cur->head;
191+
}
192+
return nullptr;
193+
}
194+
132195
//
133196
// TempSpace::TempSpace
134197
//
@@ -140,7 +203,7 @@ TempSpace::TempSpace(MemoryPool& p, const PathName& prefix, bool dynamic)
140203
logicalSize(0), physicalSize(0), localCacheUsage(0),
141204
head(NULL), tail(NULL), tempFiles(p),
142205
initialBuffer(p), initiallyDynamic(dynamic),
143-
freeSegments(p), freeSegmentLastPointers(p)
206+
freeSegments(p), freeSegmentsBySize(p)
144207
{
145208
if (!tempDirs)
146209
{
@@ -476,28 +539,15 @@ offset_t TempSpace::allocateSpace(FB_SIZE_T size)
476539
{
477540
// Find the best available space. This is defined as the smallest free space
478541
// that is big enough. This preserves large blocks.
479-
Segment* best = nullptr;
480-
481-
// Search through the available space in the not used segments list
482-
if (freeSegmentLastPointers.locate(locGreatEqual, size))
483-
{
484-
SegmentLastPointer* const cur = &freeSegmentLastPointers.current();
485-
const offset_t position = cur->pop();
486-
if (cur->isEmpty())
487-
freeSegmentLastPointers.fastRemove();
488-
489-
if (!freeSegments.locate(position))
490-
fb_assert(false);
491-
492-
best = freeSegments.current();
493-
}
542+
Segment* best = freeSegmentsBySize.getSegment(size);
494543

495544
// If we didn't find any space, allocate it at the end of the file
496545
if (!best)
497546
{
498547
extend(size);
499548
return getSize() - size;
500549
}
550+
freeSegmentsBySize.removeSegment(best);
501551

502552
// Set up the return parameters
503553
const offset_t position = best->position;
@@ -514,7 +564,7 @@ offset_t TempSpace::allocateSpace(FB_SIZE_T size)
514564
freeSegments.fastRemove();
515565
}
516566
else
517-
lastPointerAdd(best);
567+
freeSegmentsBySize.addSegment(best);
518568

519569
return position;
520570
}
@@ -537,7 +587,7 @@ void TempSpace::releaseSpace(offset_t position, FB_SIZE_T size)
537587
{
538588
// The next segment is found to be adjacent
539589
Segment* const next_seg = freeSegments.current();
540-
lastPointerRemove(next_seg);
590+
freeSegmentsBySize.removeSegment(next_seg);
541591

542592
next_seg->position -= size;
543593
next_seg->size += size;
@@ -548,7 +598,7 @@ void TempSpace::releaseSpace(offset_t position, FB_SIZE_T size)
548598
Segment* const prior_seg = freeSegments.current();
549599
if (position == prior_seg->position + prior_seg->size)
550600
{
551-
lastPointerRemove(prior_seg);
601+
freeSegmentsBySize.removeSegment(prior_seg);
552602

553603
next_seg->position -= prior_seg->size;
554604
next_seg->size += prior_seg->size;
@@ -558,7 +608,7 @@ void TempSpace::releaseSpace(offset_t position, FB_SIZE_T size)
558608
}
559609
}
560610

561-
lastPointerAdd(next_seg);
611+
freeSegmentsBySize.addSegment(next_seg);
562612
return;
563613
}
564614

@@ -568,16 +618,16 @@ void TempSpace::releaseSpace(offset_t position, FB_SIZE_T size)
568618
Segment* const prior_seg = freeSegments.current();
569619
if (position == prior_seg->position + prior_seg->size)
570620
{
571-
lastPointerRemove(prior_seg);
621+
freeSegmentsBySize.removeSegment(prior_seg);
572622
prior_seg->size += size;
573-
lastPointerAdd(prior_seg);
623+
freeSegmentsBySize.addSegment(prior_seg);
574624
return;
575625
}
576626
}
577627

578628
Segment* new_seg = FB_NEW_POOL(pool) Segment(position, size);
579-
freeSegments.add(new_seg);
580-
lastPointerAdd(new_seg);
629+
if (freeSegments.add(new_seg))
630+
freeSegmentsBySize.addSegment(new_seg);
581631
}
582632

583633
//
@@ -689,7 +739,7 @@ ULONG TempSpace::allocateBatch(ULONG count, FB_SIZE_T minSize, FB_SIZE_T maxSize
689739
fb_assert(p == mem);
690740
fb_assert(seek1 == freeSeek);
691741
#endif
692-
lastPointerRemove(freeSpace);
742+
freeSegmentsBySize.removeSegment(freeSpace);
693743

694744
if (freeSeek != freeSpace->position)
695745
{
@@ -702,7 +752,7 @@ ULONG TempSpace::allocateBatch(ULONG count, FB_SIZE_T minSize, FB_SIZE_T maxSize
702752

703753
if (!freeSegments.add(skip_space))
704754
fb_assert(false);
705-
lastPointerAdd(skip_space);
755+
freeSegmentsBySize.addSegment(skip_space);
706756

707757
if (!freeSegments.locate(freeSpace->position))
708758
fb_assert(false);
@@ -725,7 +775,7 @@ ULONG TempSpace::allocateBatch(ULONG count, FB_SIZE_T minSize, FB_SIZE_T maxSize
725775
is_positioned = freeSegments.fastRemove();
726776
}
727777
else
728-
lastPointerAdd(freeSpace);
778+
freeSegmentsBySize.addSegment(freeSpace);
729779
}
730780
else
731781
{

src/jrd/TempSpace.h

Lines changed: 20 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -197,33 +197,20 @@ class TempSpace : public Firebird::File
197197
}
198198
};
199199

200-
class SegmentLastPointer
200+
class SegmentsStack
201201
{
202202
public:
203-
SegmentLastPointer() : size(0), last(nullptr)
203+
SegmentsStack() : size(0), head(nullptr)
204204
{}
205205

206-
SegmentLastPointer(offset_t aSize, Segment* aSegment) :
207-
size(aSize), last(aSegment)
206+
SegmentsStack(offset_t aSize, Segment* aSegment) :
207+
size(aSize), head(aSegment)
208208
{}
209209

210-
offset_t pop()
211-
{
212-
fb_assert(last);
213-
offset_t last_position = last->position;
214-
last = last->prev;
215-
return last_position;
216-
}
217-
218-
bool isEmpty()
219-
{
220-
return !last;
221-
}
222-
223210
offset_t size;
224-
Segment* last;
211+
Segment* head;
225212

226-
static const offset_t& generate(const void* /*sender*/, const SegmentLastPointer& segment)
213+
static const offset_t& generate(const void* /*sender*/, const SegmentsStack& segment)
227214
{
228215
return segment.size;
229216
}
@@ -241,53 +228,25 @@ class TempSpace : public Firebird::File
241228
bool initiallyDynamic;
242229

243230
typedef Firebird::BePlusTree<Segment*, offset_t, Segment> FreeSegmentTree;
244-
FreeSegmentTree freeSegments;
231+
typedef Firebird::BePlusTree<SegmentsStack, offset_t, SegmentsStack> FreeSegmentsStackTree;
245232

246-
typedef Firebird::BePlusTree<SegmentLastPointer, offset_t, SegmentLastPointer> FreeSegmentLastPointerTree;
247-
FreeSegmentLastPointerTree freeSegmentLastPointers;
248-
249-
inline void lastPointerAdd(Segment* const segment)
233+
class FreeSegmentBySize
250234
{
251-
if (freeSegmentLastPointers.locate(segment->size))
252-
{
253-
SegmentLastPointer* const pointer = &freeSegmentLastPointers.current();
254-
segment->next = nullptr;
255-
segment->prev = pointer->last;
256-
pointer->last->next = segment;
257-
pointer->last = segment;
258-
}
259-
else
260-
{
261-
segment->prev = nullptr;
262-
segment->next = nullptr;
263-
freeSegmentLastPointers.add(SegmentLastPointer(segment->size, segment));
264-
}
265-
}
235+
public:
236+
FreeSegmentBySize(MemoryPool& pool)
237+
: m_items(pool)
238+
{}
266239

267-
inline void lastPointerRemove(Segment* const segment)
268-
{
269-
if (segment->next == nullptr)
270-
{
271-
if (!freeSegmentLastPointers.locate(segment->size))
272-
fb_assert(false);
240+
void addSegment(Segment* const segment);
241+
void removeSegment(Segment* const segment);
242+
Segment* getSegment(FB_SIZE_T size);
273243

274-
SegmentLastPointer* pointer = &freeSegmentLastPointers.current();
275-
if (segment->prev)
276-
{
277-
segment->prev->next = nullptr;
278-
pointer->last = segment->prev;
279-
}
280-
else
281-
freeSegmentLastPointers.fastRemove();
282-
}
283-
else
284-
{
285-
if (segment->prev)
286-
segment->prev->next = segment->next;
244+
private:
245+
FreeSegmentsStackTree m_items;
246+
};
287247

288-
segment->next->prev = segment->prev;
289-
}
290-
}
248+
FreeSegmentTree freeSegments;
249+
FreeSegmentBySize freeSegmentsBySize;
291250

292251
static Firebird::GlobalPtr<Firebird::Mutex> initMutex;
293252
static Firebird::TempDirectoryList* tempDirs;

0 commit comments

Comments
 (0)