github.com/scaleoutsean/fusego@v0.0.0-20220224074057-4a6429e46bb8/internal/buffer/in_message.go (about)

     1  // Copyright 2015 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package buffer
    16  
    17  import (
    18  	"fmt"
    19  	"io"
    20  	"syscall"
    21  	"unsafe"
    22  
    23  	"github.com/scaleoutsean/fusego/internal/fusekernel"
    24  )
    25  
    26  // All requests read from the kernel, without data, are shorter than
    27  // this.
    28  const pageSize = 4096
    29  
    30  func init() {
    31  	// Confirm the page size.
    32  	if syscall.Getpagesize() != pageSize {
    33  		panic(fmt.Sprintf("Page size is unexpectedly %d", syscall.Getpagesize()))
    34  	}
    35  }
    36  
    37  // We size the buffer to have enough room for a fuse request plus data
    38  // associated with a write request.
    39  const bufSize = pageSize + MaxWriteSize
    40  
    41  // An incoming message from the kernel, including leading fusekernel.InHeader
    42  // struct. Provides storage for messages and convenient access to their
    43  // contents.
    44  type InMessage struct {
    45  	remaining []byte
    46  	storage   [bufSize]byte
    47  }
    48  
    49  // Initialize with the data read by a single call to r.Read. The first call to
    50  // Consume will consume the bytes directly after the fusekernel.InHeader
    51  // struct.
    52  func (m *InMessage) Init(r io.Reader) error {
    53  	n, err := r.Read(m.storage[:])
    54  	if err != nil {
    55  		return err
    56  	}
    57  
    58  	// Make sure the message is long enough.
    59  	const headerSize = unsafe.Sizeof(fusekernel.InHeader{})
    60  	if uintptr(n) < headerSize {
    61  		return fmt.Errorf("Unexpectedly read only %d bytes.", n)
    62  	}
    63  
    64  	m.remaining = m.storage[headerSize:n]
    65  
    66  	// Check the header's length.
    67  	if int(m.Header().Len) != n {
    68  		return fmt.Errorf(
    69  			"Header says %d bytes, but we read %d",
    70  			m.Header().Len,
    71  			n)
    72  	}
    73  
    74  	return nil
    75  }
    76  
    77  // Return a reference to the header read in the most recent call to Init.
    78  func (m *InMessage) Header() *fusekernel.InHeader {
    79  	return (*fusekernel.InHeader)(unsafe.Pointer(&m.storage[0]))
    80  }
    81  
    82  // Return the number of bytes left to consume.
    83  func (m *InMessage) Len() uintptr {
    84  	return uintptr(len(m.remaining))
    85  }
    86  
    87  // Consume the next n bytes from the message, returning a nil pointer if there
    88  // are fewer than n bytes available.
    89  func (m *InMessage) Consume(n uintptr) unsafe.Pointer {
    90  	if m.Len() == 0 || n > m.Len() {
    91  		return nil
    92  	}
    93  
    94  	p := unsafe.Pointer(&m.remaining[0])
    95  	m.remaining = m.remaining[n:]
    96  
    97  	return p
    98  }
    99  
   100  // Equivalent to Consume, except returns a slice of bytes. The result will be
   101  // nil if Consume would fail.
   102  func (m *InMessage) ConsumeBytes(n uintptr) []byte {
   103  	if n > m.Len() {
   104  		return nil
   105  	}
   106  
   107  	b := m.remaining[:n]
   108  	m.remaining = m.remaining[n:]
   109  
   110  	return b
   111  }