@@ -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 {
0 commit comments