github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/fuse/fuse_file.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:43</date>
    10  //</624450112843681792>
    11  
    12  
    13  //+构建Linux Darwin Freebsd
    14  
    15  package fuse
    16  
    17  import (
    18  	"errors"
    19  	"io"
    20  	"os"
    21  	"sync"
    22  
    23  	"bazil.org/fuse"
    24  	"bazil.org/fuse/fs"
    25  	"github.com/ethereum/go-ethereum/swarm/log"
    26  	"github.com/ethereum/go-ethereum/swarm/storage"
    27  	"golang.org/x/net/context"
    28  )
    29  
    30  const (
    31  MaxAppendFileSize = 10485760 //10MB
    32  )
    33  
    34  var (
    35  	errInvalidOffset           = errors.New("Invalid offset during write")
    36  	errFileSizeMaxLimixReached = errors.New("File size exceeded max limit")
    37  )
    38  
    39  var (
    40  	_ fs.Node         = (*SwarmFile)(nil)
    41  	_ fs.HandleReader = (*SwarmFile)(nil)
    42  	_ fs.HandleWriter = (*SwarmFile)(nil)
    43  )
    44  
    45  type SwarmFile struct {
    46  	inode    uint64
    47  	name     string
    48  	path     string
    49  	addr     storage.Address
    50  	fileSize int64
    51  	reader   storage.LazySectionReader
    52  
    53  	mountInfo *MountInfo
    54  	lock      *sync.RWMutex
    55  }
    56  
    57  func NewSwarmFile(path, fname string, minfo *MountInfo) *SwarmFile {
    58  	newFile := &SwarmFile{
    59  		inode:    NewInode(),
    60  		name:     fname,
    61  		path:     path,
    62  		addr:     nil,
    63  fileSize: -1, //-1意味着,文件已经存在于Swarm中,您只需从Swarm中获取大小即可。
    64  		reader:   nil,
    65  
    66  		mountInfo: minfo,
    67  		lock:      &sync.RWMutex{},
    68  	}
    69  	return newFile
    70  }
    71  
    72  func (sf *SwarmFile) Attr(ctx context.Context, a *fuse.Attr) error {
    73  	log.Debug("swarmfs Attr", "path", sf.path)
    74  	sf.lock.Lock()
    75  	defer sf.lock.Unlock()
    76  	a.Inode = sf.inode
    77  //TODO:需要获取权限作为参数
    78  	a.Mode = 0700
    79  	a.Uid = uint32(os.Getuid())
    80  	a.Gid = uint32(os.Getegid())
    81  
    82  	if sf.fileSize == -1 {
    83  		reader, _ := sf.mountInfo.swarmApi.Retrieve(ctx, sf.addr)
    84  		quitC := make(chan bool)
    85  		size, err := reader.Size(ctx, quitC)
    86  		if err != nil {
    87  			log.Error("Couldnt get size of file %s : %v", sf.path, err)
    88  			return err
    89  		}
    90  		sf.fileSize = size
    91  		log.Trace("swarmfs Attr", "size", size)
    92  		close(quitC)
    93  	}
    94  	a.Size = uint64(sf.fileSize)
    95  	return nil
    96  }
    97  
    98  func (sf *SwarmFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
    99  	log.Debug("swarmfs Read", "path", sf.path, "req.String", req.String())
   100  	sf.lock.RLock()
   101  	defer sf.lock.RUnlock()
   102  	if sf.reader == nil {
   103  		sf.reader, _ = sf.mountInfo.swarmApi.Retrieve(ctx, sf.addr)
   104  	}
   105  	buf := make([]byte, req.Size)
   106  	n, err := sf.reader.ReadAt(buf, req.Offset)
   107  	if err == io.ErrUnexpectedEOF || err == io.EOF {
   108  		err = nil
   109  	}
   110  	resp.Data = buf[:n]
   111  	sf.reader = nil
   112  
   113  	return err
   114  }
   115  
   116  func (sf *SwarmFile) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
   117  	log.Debug("swarmfs Write", "path", sf.path, "req.String", req.String())
   118  	if sf.fileSize == 0 && req.Offset == 0 {
   119  //创建新文件
   120  		err := addFileToSwarm(sf, req.Data, len(req.Data))
   121  		if err != nil {
   122  			return err
   123  		}
   124  		resp.Size = len(req.Data)
   125  	} else if req.Offset <= sf.fileSize {
   126  		totalSize := sf.fileSize + int64(len(req.Data))
   127  		if totalSize > MaxAppendFileSize {
   128  			log.Warn("swarmfs Append file size reached (%v) : (%v)", sf.fileSize, len(req.Data))
   129  			return errFileSizeMaxLimixReached
   130  		}
   131  
   132  		err := appendToExistingFileInSwarm(sf, req.Data, req.Offset, int64(len(req.Data)))
   133  		if err != nil {
   134  			return err
   135  		}
   136  		resp.Size = len(req.Data)
   137  	} else {
   138  		log.Warn("swarmfs Invalid write request size(%v) : off(%v)", sf.fileSize, req.Offset)
   139  		return errInvalidOffset
   140  	}
   141  	return nil
   142  }
   143