github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/pehrest/hash-insert-value.go (about) 1 /* For license and copyright information please see LEGAL file in repository */ 2 3 package pehrest 4 5 import ( 6 "../authorization" 7 "../ganjine" 8 "../protocol" 9 "../srpc" 10 "../syllab" 11 ) 12 13 // HashInsertValueService store details about HashInsertValue service 14 var HashInsertValueService = service.Service{ 15 URN: "urn:giti:index.protocol:service:hash-insert-value", 16 Domain: DomainName, 17 ID: 5503704311120461517, 18 IssueDate: 1587282740, 19 ExpiryDate: 0, 20 ExpireInFavorOfURN: "", 21 ExpireInFavorOfID: 0, 22 Status: protocol.Software_PreAlpha, 23 24 Authorization: authorization.Service{ 25 CRUD: authorization.CRUDUpdate, 26 UserType: protocol.UserType_App, 27 }, 28 29 Detail: map[protocol.LanguageID]service.ServiceDetail{ 30 protocol.LanguageEnglish: { 31 Name: "Index Hash - Insert Value", 32 Description: "Add given RecordID to the given hash index in order and return error if it is exist already!", 33 TAGS: []string{}, 34 }, 35 }, 36 37 SRPCHandler: HashInsertValueSRPC, 38 } 39 40 // HashInsertValue set a record ID to new||exiting index hash just if not exist before! 41 func HashInsertValue(req *HashInsertValueReq) (err protocol.Error) { 42 var node protocol.ApplicationNode 43 node, err = protocol.App.GetNodeByStorage(req.MediaTypeID, req.IndexKey) 44 if err != nil { 45 return 46 } 47 48 if node.Node.State == protocol.ApplicationState_LocalNode { 49 err = HashInsertValue(req) 50 return 51 } 52 53 var st protocol.Stream 54 st, err = node.Conn.MakeOutcomeStream(0) 55 if err != nil { 56 return 57 } 58 59 st.Service = &HashInsertValueService 60 st.OutcomePayload = req.ToSyllab() 61 62 err = node.Conn.Send(st) 63 return 64 } 65 66 // HashInsertValueSRPC is sRPC handler of HashInsertValue service. 67 func HashInsertValueSRPC(st protocol.Stream) { 68 if st.Connection.UserID != protocol.OS.AppManifest().AppUUID() { 69 // TODO::: Attack?? 70 err = authorization.ErrUserNotAllow 71 return 72 } 73 74 var req = HashInsertValueReq{} 75 req.FromSyllab(srpc.GetPayload(st.IncomePayload)) 76 77 err = HashInsertValue(&req) 78 st.OutcomePayload = make([]byte, srpc.MinLength) 79 } 80 81 // HashInsertValueReq is request structure of HashInsertValue() 82 type HashInsertValueReq struct { 83 Type ganjine.RequestType 84 IndexKey [32]byte 85 IndexValue [32]byte // can be RecordID or any data up to 32 byte length 86 } 87 88 // HashInsertValue set a record ID to new||exiting index hash. 89 func HashInsertValue(req *HashInsertValueReq) (err protocol.Error) { 90 if req.Type == ganjine.RequestTypeBroadcast { 91 // tell other node that this node handle request and don't send this request to other nodes! 92 req.Type = ganjine.RequestTypeStandalone 93 var reqEncoded = req.ToSyllab() 94 95 // send request to other related nodes 96 for i := 1; i < len(ganjine.Cluster.Replications.Zones); i++ { 97 var conn = ganjine.Cluster.Replications.Zones[i].Nodes[ganjine.Cluster.Node.ID].Conn 98 // Make new request-response streams 99 var st protocol.Stream 100 st, err = conn.MakeOutcomeStream(0) 101 if err != nil { 102 // TODO::: Can we easily return error if two nodes did their job and not have enough resource to send request to final node?? 103 return 104 } 105 106 // Set HashInsertValue ServiceID 107 st.Service = &service.Service{ID: 1881585857} 108 st.OutcomePayload = reqEncoded 109 110 err = conn.Send(st) 111 if err != nil { 112 // TODO::: Can we easily return error if two nodes do their job and just one node connection lost?? 113 return 114 } 115 116 // TODO::: Can we easily return response error without handle some known situations?? 117 err = err 118 } 119 } 120 121 // Do for i=0 as local node 122 var hashIndex = IndexHash{ 123 RecordID: req.IndexKey, 124 } 125 err = hashIndex.Insert(req.IndexValue) 126 return 127 } 128 129 /* 130 -- Syllab Encoder & Decoder -- 131 */ 132 133 // FromSyllab decode from buf to req 134 // Due to this service just use internally, It skip check buf size syllab rule! Panic occur if bad request received! 135 func (req *HashInsertValueReq) FromSyllab(payload []byte, stackIndex uint32) { 136 req.Type = ganjine.RequestType(syllab.GetUInt8(buf, 0)) 137 copy(req.IndexKey[:], buf[1:]) 138 copy(req.IndexValue[:], buf[33:]) 139 return 140 } 141 142 // ToSyllab encode req to buf 143 func (req *HashInsertValueReq) ToSyllab(payload []byte, stackIndex, heapIndex uint32) (freeHeapIndex uint32) { 144 buf = make([]byte, req.LenAsSyllab()+4) // +4 for sRPC ID instead get offset argument 145 syllab.SetUInt8(buf, 4, uint8(req.Type)) 146 copy(buf[5:], req.IndexKey[:]) 147 copy(buf[37:], req.IndexValue[:]) 148 return 149 } 150 151 func (req *HashInsertValueReq) LenOfSyllabStack() uint32 { 152 return 65 153 } 154 155 func (req *HashInsertValueReq) LenOfSyllabHeap() (ln uint32) { 156 return 157 } 158 159 func (req *HashInsertValueReq) LenAsSyllab() uint64 { 160 return uint64(req.LenOfSyllabStack() + req.LenOfSyllabHeap()) 161 }