Skip to content

Commit 6c68b9e

Browse files
headerfs: use truncateHeaders on headerFile
1 parent 0d92ab1 commit 6c68b9e

File tree

2 files changed

+66
-65
lines changed

2 files changed

+66
-65
lines changed

headerfs/store.go

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77
"os"
88
"path/filepath"
9+
"runtime"
910
"sync"
1011
"time"
1112

@@ -109,6 +110,63 @@ type headerFile struct {
109110
file File
110111
}
111112

113+
// truncateHeaders truncates one or more headers from the end of the header
114+
// file. This can be used in the case of a re-org to remove headers from the end
115+
// of the main chain.
116+
//
117+
// The numHeaders parameter specifies how many headers to truncate. If
118+
// numHeaders is 1, this is equivalent to the old singleTruncate behavior.
119+
//
120+
// This function handles platform-specific differences in file truncation. On
121+
// Windows, the file is closed, truncated, and reopened due to Windows
122+
// limitations on truncating open files. On other platforms, the file is
123+
// truncated directly without closing.
124+
func (h *headerFile) truncateHeaders(numHeaders uint32,
125+
headerType HeaderType) error {
126+
127+
// If numHeaders is 0, treat it as a no-op and return no error.
128+
if numHeaders == 0 {
129+
return nil
130+
}
131+
132+
// In order to truncate the file, we'll need to grab the absolute size
133+
// of the file as it stands currently.
134+
fileInfo, err := h.file.Stat()
135+
if err != nil {
136+
return err
137+
}
138+
fileSize := fileInfo.Size()
139+
140+
// Calculate the total bytes to truncate based on number of headers.
141+
headerTypeSize, err := headerType.Size()
142+
if err != nil {
143+
return err
144+
}
145+
truncateLength := int64(numHeaders) * int64(headerTypeSize)
146+
147+
// Finally, we'll use both of these values to calculate the new size of
148+
// the file and truncate it accordingly.
149+
newSize := fileSize - truncateLength
150+
151+
// On Windows, we need to close, truncate, and reopen the file.
152+
if runtime.GOOS == "windows" {
153+
fileName := h.file.Name()
154+
if err = h.file.Close(); err != nil {
155+
return err
156+
}
157+
158+
if err = os.Truncate(fileName, newSize); err != nil {
159+
return err
160+
}
161+
162+
fileFlags := os.O_RDWR | os.O_APPEND | os.O_CREATE
163+
h.file, err = os.OpenFile(fileName, fileFlags, 0644)
164+
return err
165+
}
166+
167+
return h.file.Truncate(newSize)
168+
}
169+
112170
// headerStore combines a on-disk set of headers within a flat file in addition
113171
// to a database which indexes that flat file. Together, these two abstractions
114172
// can be used in order to build an indexed header store for any type of
@@ -247,12 +305,9 @@ func NewBlockHeaderStore(filePath string, db walletdb.DB,
247305

248306
// Otherwise, we'll need to truncate the file until it matches the
249307
// current index tip.
250-
for fileHeight > tipHeight {
251-
if err := bhs.singleTruncate(); err != nil {
252-
return nil, err
253-
}
254-
255-
fileHeight--
308+
err = bhs.truncateHeaders(fileHeight-tipHeight, bhs.indexType)
309+
if err != nil {
310+
return nil, err
256311
}
257312

258313
return bhs, nil
@@ -362,13 +417,12 @@ func (h *blockHeaderStore) RollbackLastBlock() (*BlockStamp, error) {
362417
if err != nil {
363418
return nil, err
364419
}
365-
366420
prevHeaderHash := prevHeader.BlockHash()
367421

368422
// Now that we have the information we need to return from this
369423
// function, we can now truncate the header file, and then use the hash
370424
// of the prevHeader to set the proper index chain tip.
371-
if err := h.singleTruncate(); err != nil {
425+
if err := h.truncateHeaders(1, h.indexType); err != nil {
372426
return nil, err
373427
}
374428
if err := h.truncateIndex(&prevHeaderHash, true); err != nil {
@@ -767,16 +821,11 @@ func NewFilterHeaderStore(filePath string, db walletdb.DB,
767821

768822
// Otherwise, we'll need to truncate the file until it matches the
769823
// current index tip.
770-
for fileHeight > tipHeight {
771-
if err := fhs.singleTruncate(); err != nil {
772-
return nil, err
773-
}
774-
775-
fileHeight--
824+
err = fhs.truncateHeaders(fileHeight-tipHeight, fhs.indexType)
825+
if err != nil {
826+
return nil, err
776827
}
777828

778-
// TODO(roasbeef): make above into func
779-
780829
return fhs, nil
781830
}
782831

@@ -995,7 +1044,7 @@ func (f *filterHeaderStore) RollbackLastBlock(
9951044

9961045
// Now that we have the information we need to return from this
9971046
// function, we can now truncate both the header file and the index.
998-
if err := f.singleTruncate(); err != nil {
1047+
if err := f.truncateHeaders(1, f.indexType); err != nil {
9991048
return nil, err
10001049
}
10011050
if err := f.truncateIndex(newTip, false); err != nil {

headerfs/truncate.go

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)