Skip to content

Commit 86c59ba

Browse files
committed
Refactor: Improve buffer management logic and enhance error handling in BufferMgr
1 parent 5077bab commit 86c59ba

1 file changed

Lines changed: 32 additions & 26 deletions

File tree

buffer/bufferMgr.go

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type BufferMgr struct {
2121
numAvailable int
2222
availableCh chan struct{}
2323

24-
// LRU/Access tracking fields
24+
// Access tracking fields (for LRU or similar).
2525
accessCounter uint64
2626

2727
// Optional statistics.
@@ -39,68 +39,73 @@ func NewBufferMgr(fm *kfile.FileMgr, numBuffs int, policy EvictionPolicy) *Buffe
3939
}
4040
}
4141

42-
// Pin retrieves (or creates) a Buffer for the given block, possibly blocking until one is available.
43-
// The block is looked up (or allocated) using the provided eviction policy.
42+
// Pin attempts to retrieve a buffer for the given block, possibly blocking until a buffer becomes available.
43+
// If no buffers become available within MaxTime, an error is returned.
4444
func (bm *BufferMgr) Pin(blk *kfile.BlockId) (*Buffer, error) {
4545
startTime := time.Now()
4646

47-
// Main loop: try to obtain a buffer until success or timeout.
47+
// Main loop: retry until success or timeout.
4848
for {
4949
bm.mu.Lock()
5050

51-
// Try to get the buffer from the policy.
52-
buff, err := bm.Policy.Get(*blk) // returns pinned buffer if found.
53-
if err != nil {
54-
// Log the error (here we simply print it).
55-
fmt.Printf("warning: error getting buffer from policy: %v\n", err)
56-
} else {
51+
buff, getErr := bm.Policy.Get(*blk)
52+
switch {
53+
case getErr != nil:
54+
// Log the error from Policy.Get but don’t necessarily return unless it's critical.
55+
// The 'not found' scenario might not be an error per se; it could simply return (nil, nil).
56+
fmt.Printf("debug: Policy.Get returned an error: %v\n", getErr)
57+
58+
case buff != nil:
59+
// We found the buffer in the policy -> It's a "hit".
5760
bm.hitCounter++
61+
bm.mu.Unlock()
62+
return buff, nil
5863
}
59-
// If not found and there is availability, allocate a new buffer.
64+
65+
// Not found in the policy, so we need a new buffer if one is available.
6066
if buff == nil && bm.numAvailable > 0 {
6167
bm.missCounter++
62-
buff, err = bm.Policy.AllocateBufferForBlock(*blk)
63-
if err != nil {
68+
newBuff, allocErr := bm.Policy.AllocateBufferForBlock(*blk)
69+
if allocErr != nil {
6470
bm.mu.Unlock()
65-
return nil, fmt.Errorf("failed to allocate buffer: %w", err)
71+
return nil, fmt.Errorf("failed to allocate buffer: %w", allocErr)
6672
}
6773
bm.numAvailable--
68-
}
69-
if buff != nil {
7074
bm.mu.Unlock()
71-
return buff, nil
75+
return newBuff, nil
7276
}
7377

74-
// Calculate remaining wait time.
78+
// If we reach here, it means buff == nil and bm.numAvailable == 0.
79+
80+
// Check if we’ve timed out.
7581
remaining := MaxTime - time.Since(startTime)
7682
if remaining <= 0 {
7783
bm.mu.Unlock()
7884
return nil, fmt.Errorf("no buffers available after waiting %v", MaxTime)
7985
}
80-
// Release lock and wait for a buffer to become free.
86+
87+
// Wait for a buffer to become free. Unlock while waiting.
8188
bm.mu.Unlock()
8289
select {
8390
case <-bm.availableCh:
84-
// A signal indicates a buffer is available; retry.
91+
// A buffer might have been freed; loop again.
8592
case <-time.After(remaining):
8693
return nil, fmt.Errorf("no buffers available after waiting %v", MaxTime)
8794
}
8895
}
8996
}
9097

91-
// Unpin decrements the pin count of the given buffer. If the buffer becomes unpinned,
92-
// it increments bm.numAvailable and signals availableCh that a buffer is free.
98+
// Unpin decrements the pin count of the given buffer. If it becomes unpinned,
99+
// bm.numAvailable is incremented, and a signal is sent on bm.availableCh to notify waiters.
93100
func (bm *BufferMgr) Unpin(buff *Buffer) {
94101
bm.mu.Lock()
95102
defer bm.mu.Unlock()
96103

97-
// Unpin the buffer.
98104
if err := buff.Unpin(); err != nil {
99105
// Log a warning rather than panicking.
100106
fmt.Printf("warning: Unpin called on an unpinned buffer: %v\n", err)
101107
return
102108
}
103-
// If the buffer is now unpinned, update availability.
104109
if !buff.Pinned() {
105110
bm.numAvailable++
106111
select {
@@ -110,13 +115,14 @@ func (bm *BufferMgr) Unpin(buff *Buffer) {
110115
}
111116
}
112117

113-
// updateAccessTime updates a buffer's last access time using the global access counter.
118+
// updateAccessTime sets a buffer’s lastAccessTime using a global counter,
119+
// which can be used by LRU or other replacement policies.
114120
func (bm *BufferMgr) updateAccessTime(buff *Buffer) {
115121
bm.accessCounter++
116122
buff.lastAccessTime = bm.accessCounter
117123
}
118124

119-
// available returns the number of available (unpinned) buffers.
125+
// available returns the current count of available (unpinned) buffers.
120126
func (bm *BufferMgr) available() int {
121127
bm.mu.RLock()
122128
defer bm.mu.RUnlock()

0 commit comments

Comments
 (0)