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  }