You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							90 lines
						
					
					
						
							2.6 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							90 lines
						
					
					
						
							2.6 KiB
						
					
					
				| package mount | |
| 
 | |
| import ( | |
| 	"bytes" | |
| 	"fmt" | |
| 	"github.com/seaweedfs/seaweedfs/weed/util" | |
| 	"io" | |
| 
 | |
| 	"github.com/hanwen/go-fuse/v2/fuse" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/glog" | |
| ) | |
| 
 | |
| /** | |
|  * Read data | |
|  * | |
|  * Read should send exactly the number of bytes requested except | |
|  * on EOF or error, otherwise the rest of the data will be | |
|  * substituted with zeroes.  An exception to this is when the file | |
|  * has been opened in 'direct_io' mode, in which case the return | |
|  * value of the read system call will reflect the return value of | |
|  * this operation. | |
|  * | |
|  * fi->fh will contain the value set by the open method, or will | |
|  * be undefined if the open method didn't set any value. | |
|  * | |
|  * Valid replies: | |
|  *   fuse_reply_buf | |
|  *   fuse_reply_iov | |
|  *   fuse_reply_data | |
|  *   fuse_reply_err | |
|  * | |
|  * @param req request handle | |
|  * @param ino the inode number | |
|  * @param size number of bytes to read | |
|  * @param off offset to read from | |
|  * @param fi file information | |
|  */ | |
| func (wfs *WFS) Read(cancel <-chan struct{}, in *fuse.ReadIn, buff []byte) (fuse.ReadResult, fuse.Status) { | |
| 	fh := wfs.GetHandle(FileHandleId(in.Fh)) | |
| 	if fh == nil { | |
| 		return nil, fuse.ENOENT | |
| 	} | |
| 
 | |
| 	fhActiveLock := fh.wfs.fhLockTable.AcquireLock("Read", fh.fh, util.SharedLock) | |
| 	defer fh.wfs.fhLockTable.ReleaseLock(fh.fh, fhActiveLock) | |
| 
 | |
| 	offset := int64(in.Offset) | |
| 	totalRead, err := readDataByFileHandle(buff, fh, offset) | |
| 	if err != nil { | |
| 		glog.Warningf("file handle read %s %d: %v", fh.FullPath(), totalRead, err) | |
| 		return nil, fuse.EIO | |
| 	} | |
| 
 | |
| 	if IsDebugFileReadWrite { | |
| 		// print(".") | |
| 		mirrorData := make([]byte, totalRead) | |
| 		fh.mirrorFile.ReadAt(mirrorData, offset) | |
| 		if bytes.Compare(mirrorData, buff[:totalRead]) != 0 { | |
| 
 | |
| 			againBuff := make([]byte, len(buff)) | |
| 			againRead, _ := readDataByFileHandle(againBuff, fh, offset) | |
| 			againCorrect := bytes.Compare(mirrorData, againBuff[:againRead]) == 0 | |
| 			againSame := bytes.Compare(buff[:totalRead], againBuff[:againRead]) == 0 | |
| 
 | |
| 			fmt.Printf("\ncompare %v [%d,%d) size:%d againSame:%v againCorrect:%v\n", fh.mirrorFile.Name(), offset, offset+totalRead, totalRead, againSame, againCorrect) | |
| 			//fmt.Printf("read mirrow data: %v\n", mirrorData) | |
| 			//fmt.Printf("read actual data: %v\n", againBuff[:totalRead]) | |
| 		} | |
| 	} | |
| 
 | |
| 	return fuse.ReadResultData(buff[:totalRead]), fuse.OK | |
| } | |
| 
 | |
| func readDataByFileHandle(buff []byte, fhIn *FileHandle, offset int64) (int64, error) { | |
| 	// read data from source file | |
| 	size := len(buff) | |
| 	fhIn.lockForRead(offset, size) | |
| 	defer fhIn.unlockForRead(offset, size) | |
| 
 | |
| 	n, tsNs, err := fhIn.readFromChunks(buff, offset) | |
| 	if err == nil || err == io.EOF { | |
| 		maxStop := fhIn.readFromDirtyPages(buff, offset, tsNs) | |
| 		n = max(maxStop-offset, n) | |
| 	} | |
| 	if err == io.EOF { | |
| 		err = nil | |
| 	} | |
| 	return n, err | |
| }
 |