github.com/GuanceCloud/cliutils@v1.1.21/diskcache/switch.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 package diskcache 7 8 import ( 9 "fmt" 10 "io" 11 "os" 12 "time" 13 ) 14 15 // switch to next file remembered in .pos file. 16 func (c *DiskCache) loadUnfinishedFile() error { 17 if _, err := os.Stat(c.pos.fname); err != nil { 18 return nil // .pos file not exist 19 } 20 21 pos, err := posFromFile(c.pos.fname) 22 if err != nil { 23 return fmt.Errorf("posFromFile: %w", err) 24 } 25 26 if pos == nil { 27 return nil 28 } 29 30 // check file's healty 31 if _, err := os.Stat(string(pos.Name)); err != nil { // not exist 32 if err := c.pos.reset(); err != nil { 33 return err 34 } 35 36 return nil 37 } 38 39 // invalid .pos, ignored 40 if pos.Seek <= 0 { 41 return nil 42 } 43 44 fd, err := os.OpenFile(string(pos.Name), os.O_RDONLY, c.filePerms) 45 if err != nil { 46 return fmt.Errorf("OpenFile: %w", err) 47 } 48 49 if _, err := fd.Seek(pos.Seek, io.SeekStart); err != nil { 50 return fmt.Errorf("Seek(%q: %d, 0): %w", pos.Name, pos.Seek, err) 51 } 52 53 c.rfd = fd 54 c.curReadfile = string(pos.Name) 55 c.pos.Name = pos.Name 56 c.pos.Seek = pos.Seek 57 58 return nil 59 } 60 61 // open next read file. 62 func (c *DiskCache) doSwitchNextFile() error { 63 c.rwlock.Lock() 64 defer c.rwlock.Unlock() 65 66 if len(c.dataFiles) == 0 { 67 return nil 68 } else { 69 c.curReadfile = c.dataFiles[0] 70 } 71 72 fd, err := os.OpenFile(c.curReadfile, os.O_RDONLY, c.filePerms) 73 if err != nil { 74 return fmt.Errorf("under switchNextFile, OpenFile: %w, datafile: %+#v, ", err, c.dataFiles) 75 } 76 77 c.rfd = fd 78 79 if !c.noPos { 80 c.pos.Name = []byte(c.curReadfile) 81 c.pos.Seek = 0 82 if err := c.pos.dumpFile(); err != nil { 83 return err 84 } 85 } 86 87 return nil 88 } 89 90 // open write file. 91 func (c *DiskCache) openWriteFile() error { 92 if fi, err := os.Stat(c.curWriteFile); err == nil { // file exists 93 if fi.IsDir() { 94 return fmt.Errorf("data file should not be dir") 95 } 96 97 c.curBatchSize = fi.Size() 98 } else { 99 // file not exists 100 c.curBatchSize = 0 101 } 102 103 // write append fd, always write to the same-name file 104 wfd, err := os.OpenFile(c.curWriteFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, c.filePerms) 105 if err != nil { 106 return fmt.Errorf("under openWriteFile, OpenFile: %w", err) 107 } 108 109 c.wfdLastWrite = time.Now() 110 c.wfd = wfd 111 return nil 112 }