github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/fuse/fuse_file.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  //
    26  
    27  package fuse
    28  
    29  import (
    30  	"errors"
    31  	"io"
    32  	"os"
    33  	"sync"
    34  
    35  	"bazil.org/fuse"
    36  	"bazil.org/fuse/fs"
    37  	"github.com/ethereum/go-ethereum/swarm/log"
    38  	"github.com/ethereum/go-ethereum/swarm/storage"
    39  	"golang.org/x/net/context"
    40  )
    41  
    42  const (
    43  MaxAppendFileSize = 10485760 //
    44  )
    45  
    46  var (
    47  	errInvalidOffset           = errors.New("Invalid offset during write")
    48  	errFileSizeMaxLimixReached = errors.New("File size exceeded max limit")
    49  )
    50  
    51  var (
    52  	_ fs.Node         = (*SwarmFile)(nil)
    53  	_ fs.HandleReader = (*SwarmFile)(nil)
    54  	_ fs.HandleWriter = (*SwarmFile)(nil)
    55  )
    56  
    57  type SwarmFile struct {
    58  	inode    uint64
    59  	name     string
    60  	path     string
    61  	addr     storage.Address
    62  	fileSize int64
    63  	reader   storage.LazySectionReader
    64  
    65  	mountInfo *MountInfo
    66  	lock      *sync.RWMutex
    67  }
    68  
    69  func NewSwarmFile(path, fname string, minfo *MountInfo) *SwarmFile {
    70  	newFile := &SwarmFile{
    71  		inode:    NewInode(),
    72  		name:     fname,
    73  		path:     path,
    74  		addr:     nil,
    75  fileSize: -1, //
    76  		reader:   nil,
    77  
    78  		mountInfo: minfo,
    79  		lock:      &sync.RWMutex{},
    80  	}
    81  	return newFile
    82  }
    83  
    84  func (sf *SwarmFile) Attr(ctx context.Context, a *fuse.Attr) error {
    85  	log.Debug("swarmfs Attr", "path", sf.path)
    86  	sf.lock.Lock()
    87  	defer sf.lock.Unlock()
    88  	a.Inode = sf.inode
    89  //
    90  	a.Mode = 0700
    91  	a.Uid = uint32(os.Getuid())
    92  	a.Gid = uint32(os.Getegid())
    93  
    94  	if sf.fileSize == -1 {
    95  		reader, _ := sf.mountInfo.swarmApi.Retrieve(ctx, sf.addr)
    96  		quitC := make(chan bool)
    97  		size, err := reader.Size(ctx, quitC)
    98  		if err != nil {
    99  			log.Error("Couldnt get size of file %s : %v", sf.path, err)
   100  			return err
   101  		}
   102  		sf.fileSize = size
   103  		log.Trace("swarmfs Attr", "size", size)
   104  		close(quitC)
   105  	}
   106  	a.Size = uint64(sf.fileSize)
   107  	return nil
   108  }
   109  
   110  func (sf *SwarmFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
   111  	log.Debug("swarmfs Read", "path", sf.path, "req.String", req.String())
   112  	sf.lock.RLock()
   113  	defer sf.lock.RUnlock()
   114  	if sf.reader == nil {
   115  		sf.reader, _ = sf.mountInfo.swarmApi.Retrieve(ctx, sf.addr)
   116  	}
   117  	buf := make([]byte, req.Size)
   118  	n, err := sf.reader.ReadAt(buf, req.Offset)
   119  	if err == io.ErrUnexpectedEOF || err == io.EOF {
   120  		err = nil
   121  	}
   122  	resp.Data = buf[:n]
   123  	sf.reader = nil
   124  
   125  	return err
   126  }
   127  
   128  func (sf *SwarmFile) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
   129  	log.Debug("swarmfs Write", "path", sf.path, "req.String", req.String())
   130  	if sf.fileSize == 0 && req.Offset == 0 {
   131  //
   132  		err := addFileToSwarm(sf, req.Data, len(req.Data))
   133  		if err != nil {
   134  			return err
   135  		}
   136  		resp.Size = len(req.Data)
   137  	} else if req.Offset <= sf.fileSize {
   138  		totalSize := sf.fileSize + int64(len(req.Data))
   139  		if totalSize > MaxAppendFileSize {
   140  			log.Warn("swarmfs Append file size reached (%v) : (%v)", sf.fileSize, len(req.Data))
   141  			return errFileSizeMaxLimixReached
   142  		}
   143  
   144  		err := appendToExistingFileInSwarm(sf, req.Data, req.Offset, int64(len(req.Data)))
   145  		if err != nil {
   146  			return err
   147  		}
   148  		resp.Size = len(req.Data)
   149  	} else {
   150  		log.Warn("swarmfs Invalid write request size(%v) : off(%v)", sf.fileSize, req.Offset)
   151  		return errInvalidOffset
   152  	}
   153  	return nil
   154  }