github.com/jimmyx0x/go-ethereum@v1.10.28/core/rawdb/freezer_utils.go (about) 1 // Copyright 2022 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package rawdb 18 19 import ( 20 "io" 21 "os" 22 "path/filepath" 23 ) 24 25 // copyFrom copies data from 'srcPath' at offset 'offset' into 'destPath'. 26 // The 'destPath' is created if it doesn't exist, otherwise it is overwritten. 27 // Before the copy is executed, there is a callback can be registered to 28 // manipulate the dest file. 29 // It is perfectly valid to have destPath == srcPath. 30 func copyFrom(srcPath, destPath string, offset uint64, before func(f *os.File) error) error { 31 // Create a temp file in the same dir where we want it to wind up 32 f, err := os.CreateTemp(filepath.Dir(destPath), "*") 33 if err != nil { 34 return err 35 } 36 fname := f.Name() 37 38 // Clean up the leftover file 39 defer func() { 40 if f != nil { 41 f.Close() 42 } 43 os.Remove(fname) 44 }() 45 // Apply the given function if it's not nil before we copy 46 // the content from the src. 47 if before != nil { 48 if err := before(f); err != nil { 49 return err 50 } 51 } 52 // Open the source file 53 src, err := os.Open(srcPath) 54 if err != nil { 55 return err 56 } 57 if _, err = src.Seek(int64(offset), 0); err != nil { 58 src.Close() 59 return err 60 } 61 // io.Copy uses 32K buffer internally. 62 _, err = io.Copy(f, src) 63 if err != nil { 64 src.Close() 65 return err 66 } 67 // Rename the temporary file to the specified dest name. 68 // src may be same as dest, so needs to be closed before 69 // we do the final move. 70 src.Close() 71 72 if err := f.Close(); err != nil { 73 return err 74 } 75 f = nil 76 77 if err := os.Rename(fname, destPath); err != nil { 78 return err 79 } 80 return nil 81 } 82 83 // openFreezerFileForAppend opens a freezer table file and seeks to the end 84 func openFreezerFileForAppend(filename string) (*os.File, error) { 85 // Open the file without the O_APPEND flag 86 // because it has differing behaviour during Truncate operations 87 // on different OS's 88 file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644) 89 if err != nil { 90 return nil, err 91 } 92 // Seek to end for append 93 if _, err = file.Seek(0, io.SeekEnd); err != nil { 94 return nil, err 95 } 96 return file, nil 97 } 98 99 // openFreezerFileForReadOnly opens a freezer table file for read only access 100 func openFreezerFileForReadOnly(filename string) (*os.File, error) { 101 return os.OpenFile(filename, os.O_RDONLY, 0644) 102 } 103 104 // openFreezerFileTruncated opens a freezer table making sure it is truncated 105 func openFreezerFileTruncated(filename string) (*os.File, error) { 106 return os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) 107 } 108 109 // truncateFreezerFile resizes a freezer table file and seeks to the end 110 func truncateFreezerFile(file *os.File, size int64) error { 111 if err := file.Truncate(size); err != nil { 112 return err 113 } 114 // Seek to end for append 115 if _, err := file.Seek(0, io.SeekEnd); err != nil { 116 return err 117 } 118 return nil 119 }