github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:47</date>
    10  //</624342671074267136>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  //
    29  
    30  package fuse
    31  
    32  import (
    33  	"errors"
    34  	"io"
    35  	"os"
    36  	"sync"
    37  
    38  	"bazil.org/fuse"
    39  	"bazil.org/fuse/fs"
    40  	"github.com/ethereum/go-ethereum/swarm/log"
    41  	"github.com/ethereum/go-ethereum/swarm/storage"
    42  	"golang.org/x/net/context"
    43  )
    44  
    45  const (
    46  MaxAppendFileSize = 10485760 //
    47  )
    48  
    49  var (
    50  	errInvalidOffset           = errors.New("Invalid offset during write")
    51  	errFileSizeMaxLimixReached = errors.New("File size exceeded max limit")
    52  )
    53  
    54  var (
    55  	_ fs.Node         = (*SwarmFile)(nil)
    56  	_ fs.HandleReader = (*SwarmFile)(nil)
    57  	_ fs.HandleWriter = (*SwarmFile)(nil)
    58  )
    59  
    60  type SwarmFile struct {
    61  	inode    uint64
    62  	name     string
    63  	path     string
    64  	addr     storage.Address
    65  	fileSize int64
    66  	reader   storage.LazySectionReader
    67  
    68  	mountInfo *MountInfo
    69  	lock      *sync.RWMutex
    70  }
    71  
    72  func NewSwarmFile(path, fname string, minfo *MountInfo) *SwarmFile {
    73  	newFile := &SwarmFile{
    74  		inode:    NewInode(),
    75  		name:     fname,
    76  		path:     path,
    77  		addr:     nil,
    78  fileSize: -1, //
    79  		reader:   nil,
    80  
    81  		mountInfo: minfo,
    82  		lock:      &sync.RWMutex{},
    83  	}
    84  	return newFile
    85  }
    86  
    87  func (sf *SwarmFile) Attr(ctx context.Context, a *fuse.Attr) error {
    88  	log.Debug("swarmfs Attr", "path", sf.path)
    89  	sf.lock.Lock()
    90  	defer sf.lock.Unlock()
    91  	a.Inode = sf.inode
    92  //
    93  	a.Mode = 0700
    94  	a.Uid = uint32(os.Getuid())
    95  	a.Gid = uint32(os.Getegid())
    96  
    97  	if sf.fileSize == -1 {
    98  		reader, _ := sf.mountInfo.swarmApi.Retrieve(ctx, sf.addr)
    99  		quitC := make(chan bool)
   100  		size, err := reader.Size(ctx, quitC)
   101  		if err != nil {
   102  			log.Error("Couldnt get size of file %s : %v", sf.path, err)
   103  			return err
   104  		}
   105  		sf.fileSize = size
   106  		log.Trace("swarmfs Attr", "size", size)
   107  		close(quitC)
   108  	}
   109  	a.Size = uint64(sf.fileSize)
   110  	return nil
   111  }
   112  
   113  func (sf *SwarmFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
   114  	log.Debug("swarmfs Read", "path", sf.path, "req.String", req.String())
   115  	sf.lock.RLock()
   116  	defer sf.lock.RUnlock()
   117  	if sf.reader == nil {
   118  		sf.reader, _ = sf.mountInfo.swarmApi.Retrieve(ctx, sf.addr)
   119  	}
   120  	buf := make([]byte, req.Size)
   121  	n, err := sf.reader.ReadAt(buf, req.Offset)
   122  	if err == io.ErrUnexpectedEOF || err == io.EOF {
   123  		err = nil
   124  	}
   125  	resp.Data = buf[:n]
   126  	sf.reader = nil
   127  
   128  	return err
   129  }
   130  
   131  func (sf *SwarmFile) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
   132  	log.Debug("swarmfs Write", "path", sf.path, "req.String", req.String())
   133  	if sf.fileSize == 0 && req.Offset == 0 {
   134  //
   135  		err := addFileToSwarm(sf, req.Data, len(req.Data))
   136  		if err != nil {
   137  			return err
   138  		}
   139  		resp.Size = len(req.Data)
   140  	} else if req.Offset <= sf.fileSize {
   141  		totalSize := sf.fileSize + int64(len(req.Data))
   142  		if totalSize > MaxAppendFileSize {
   143  			log.Warn("swarmfs Append file size reached (%v) : (%v)", sf.fileSize, len(req.Data))
   144  			return errFileSizeMaxLimixReached
   145  		}
   146  
   147  		err := appendToExistingFileInSwarm(sf, req.Data, req.Offset, int64(len(req.Data)))
   148  		if err != nil {
   149  			return err
   150  		}
   151  		resp.Size = len(req.Data)
   152  	} else {
   153  		log.Warn("swarmfs Invalid write request size(%v) : off(%v)", sf.fileSize, req.Offset)
   154  		return errInvalidOffset
   155  	}
   156  	return nil
   157  }
   158