-
Notifications
You must be signed in to change notification settings - Fork 5
/
hash-transaction-finish.go
138 lines (116 loc) · 4.22 KB
/
hash-transaction-finish.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* For license and copyright information please see LEGAL file in repository */
package pehrest
import (
"../achaemenid"
"../authorization"
er "../error"
"../ganjine"
gs "../ganjine-services"
lang "../language"
"../srpc"
"../syllab"
)
// HashTransactionFinishService store details about HashTransactionFinish service
var HashTransactionFinishService = achaemenid.Service{
ID: 3635898242,
IssueDate: 1587282740,
ExpiryDate: 0,
ExpireInFavorOf: "", // English name of favor service just to show off!
ExpireInFavorOfID: 0,
Status: achaemenid.ServiceStatePreAlpha,
Authorization: authorization.Service{
CRUD: authorization.CRUDUpdate,
UserType: authorization.UserTypeApp,
},
Name: map[lang.Language]string{
lang.LanguageEnglish: "Index Hash - Transaction Finish",
},
Description: map[lang.Language]string{
lang.LanguageEnglish: `use to approve transaction!
Transaction Manager will set record and index! no further action need after this call!`,
},
TAGS: []string{
"",
},
SRPCHandler: HashTransactionFinishSRPC,
}
// HashTransactionFinishSRPC is sRPC handler of HashTransactionFinish service.
func HashTransactionFinishSRPC(st *achaemenid.Stream) {
if st.Connection.UserID != achaemenid.Server.AppID {
// TODO::: Attack??
st.Err = ganjine.ErrNotAuthorizeRequest
return
}
var req = &HashTransactionFinishReq{}
req.SyllabDecoder(srpc.GetPayload(st.IncomePayload))
st.Err = HashTransactionFinish(req)
st.OutcomePayload = make([]byte, 4)
}
// HashTransactionFinishReq is request structure of HashTransactionFinish()
type HashTransactionFinishReq struct {
Type gs.RequestType
IndexKey [32]byte
Record []byte
}
// HashTransactionFinish approve transaction!
func HashTransactionFinish(req *HashTransactionFinishReq) (err *er.Error) {
if req.Type == gs.RequestTypeBroadcast {
// tell other node that this node handle request and don't send this request to other nodes!
req.Type = gs.RequestTypeStandalone
var reqEncoded = req.SyllabEncoder()
// send request to other related nodes
for i := 1; i < len(ganjine.Cluster.Replications.Zones); i++ {
var st *achaemenid.Stream
st, err = ganjine.Cluster.Replications.Zones[i].Nodes[ganjine.Cluster.Node.ID].Conn.MakeOutcomeStream(0)
if err != nil {
// TODO::: Can we easily return error if two nodes did their job and not have enough resource to send request to final node??
return
}
st.Service = &achaemenid.Service{ID: 3635898242}
st.OutcomePayload = reqEncoded
err = achaemenid.SrpcOutcomeRequestHandler( st)
if err != nil {
// TODO::: Can we easily return error if two nodes do their job and just one node connection lost??
return
}
// TODO::: Can we easily return response error without handle some known situations??
err = st.Err
}
}
// Do for i=0 as local node
err = ganjine.Cluster.TransactionManager.FinishTransaction(req.IndexKey, req.Record)
return
}
/*
-- Syllab Encoder & Decoder --
*/
// SyllabDecoder decode from buf to req
// Due to this service just use internally, It skip check buf size syllab rule! Panic occur if bad request received!
func (req *HashTransactionFinishReq) SyllabDecoder(buf []byte) {
req.Type = gs.RequestType(syllab.GetUInt8(buf, 0))
copy(req.IndexKey[:], buf[1:])
// Due to just have one field in res structure we break syllab rules and skip get address and size of res.Record from buf
req.Record = buf[33:]
return
}
// SyllabEncoder encode req to buf
func (req *HashTransactionFinishReq) SyllabEncoder() (buf []byte) {
buf = make([]byte, req.syllabLen()+4) // +4 for sRPC ID instead get offset argument
syllab.SetUInt8(buf, 4, uint8(req.Type))
copy(buf[5:], req.IndexKey[:])
// Due to just have one field in res structure we break syllab rules and skip set address and size of res.Record in buf
// syllab.SetUInt32(buf, 37, res.syllabStackLen())
// syllab.SetUInt32(buf, 45, uint32(len(res.Record)))
copy(buf[37:], req.Record[:])
return
}
func (req *HashTransactionFinishReq) syllabStackLen() (ln uint32) {
return 33
}
func (req *HashTransactionFinishReq) syllabHeapLen() (ln uint32) {
ln = uint32(len(req.Record))
return
}
func (req *HashTransactionFinishReq) syllabLen() (ln uint64) {
return uint64(req.syllabStackLen() + req.syllabHeapLen())
}