github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/ec/intrareq.go (about)

     1  // Package ec provides erasure coding (EC) based data protection for AIStore.
     2  /*
     3   * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package ec
     6  
     7  import (
     8  	"github.com/NVIDIA/aistore/cmn/cos"
     9  	"github.com/NVIDIA/aistore/core/meta"
    10  	"github.com/NVIDIA/aistore/memsys"
    11  )
    12  
    13  const (
    14  	// a target sends a replica or slice to store on another target
    15  	// the destionation does not have to respond
    16  	reqPut intraReqType = iota
    17  	// response for requested slice/replica by another target
    18  	respPut
    19  	// a target requests a slice or replica from another target
    20  	// if the destination has the object/slice it sends it back, otherwise
    21  	//    it sets Exists=false in response header
    22  	reqGet
    23  	// a target cleans up the object and notifies all other targets to do
    24  	// cleanup as well. Destinations do not have to respond
    25  	reqDel
    26  )
    27  
    28  type (
    29  	// type of EC request between targets. If the destination has to respond it
    30  	// must set the same request type in response header
    31  	intraReqType = int
    32  
    33  	// An EC request sent via transport using Opaque field of transport.ObjHdr
    34  	// between targets inside a cluster
    35  	intraReq struct {
    36  		// Object metadata, used when a target copies replicas/slices after
    37  		// encoding or restoring the object data
    38  		meta *Metadata
    39  		// Used only by destination to answer to the sender if the destination
    40  		// has the requested metafile or replica/slice
    41  		exists bool
    42  		// The sent data is slice or full replica
    43  		isSlice bool
    44  		// bucket ID
    45  		bid uint64
    46  	}
    47  )
    48  
    49  // interface guard
    50  var (
    51  	_ cos.Unpacker = (*intraReq)(nil)
    52  	_ cos.Packer   = (*intraReq)(nil)
    53  )
    54  
    55  // Create a request header: initializes the `Sender` field with local target's
    56  // daemon ID, and sets `Exists:true` that means "local object exists".
    57  // Later `Exists` can be changed to `false` if local file is unreadable or does
    58  // not exist
    59  func newIntraReq(act intraReqType, meta *Metadata, bck *meta.Bck) *intraReq {
    60  	req := &intraReq{
    61  		meta:   meta,
    62  		exists: true,
    63  	}
    64  	if bck != nil && bck.Props != nil {
    65  		req.bid = bck.Props.BID
    66  	}
    67  	if act == reqGet && meta != nil {
    68  		req.isSlice = !meta.IsCopy
    69  	}
    70  	return req
    71  }
    72  
    73  func (r *intraReq) PackedSize() int {
    74  	if r.meta == nil {
    75  		// int8+int8+ptr_marker
    76  		return 3 + cos.SizeofI64
    77  	}
    78  	// int8+int8+ptr_marker+sizeof(meta)
    79  	return r.meta.PackedSize() + 3 + cos.SizeofI64
    80  }
    81  
    82  func (r *intraReq) Pack(packer *cos.BytePack) {
    83  	packer.WriteBool(r.exists)
    84  	packer.WriteBool(r.isSlice)
    85  	packer.WriteUint64(r.bid)
    86  	if r.meta == nil {
    87  		packer.WriteByte(0)
    88  	} else {
    89  		packer.WriteByte(1)
    90  		packer.WriteAny(r.meta)
    91  	}
    92  }
    93  
    94  func (r *intraReq) Unpack(unpacker *cos.ByteUnpack) error {
    95  	var (
    96  		i   byte
    97  		err error
    98  	)
    99  	if r.exists, err = unpacker.ReadBool(); err != nil {
   100  		return err
   101  	}
   102  	if r.isSlice, err = unpacker.ReadBool(); err != nil {
   103  		return err
   104  	}
   105  	if r.bid, err = unpacker.ReadUint64(); err != nil {
   106  		return err
   107  	}
   108  	if i, err = unpacker.ReadByte(); err != nil {
   109  		return err
   110  	}
   111  	if i == 0 {
   112  		r.meta = nil
   113  		return nil
   114  	}
   115  	r.meta = NewMetadata()
   116  	return unpacker.ReadAny(r.meta)
   117  }
   118  
   119  func (r *intraReq) NewPack(mm *memsys.MMSA) []byte {
   120  	var (
   121  		buf []byte
   122  		l   = r.PackedSize()
   123  	)
   124  	if mm != nil {
   125  		buf, _ = mm.AllocSize(int64(l))
   126  	}
   127  	packer := cos.NewPacker(buf, l)
   128  	packer.WriteAny(r)
   129  	return packer.Bytes()
   130  }