@@ -20,6 +20,7 @@ import (
20
20
)
21
21
22
22
const requestsMap = 128
23
+ const ignoreStreamId = 0
23
24
const (
24
25
connDisconnected = 0
25
26
connConnected = 1
@@ -143,6 +144,8 @@ type Connection struct {
143
144
state uint32
144
145
dec * msgpack.Decoder
145
146
lenbuf [PacketLengthBytes ]byte
147
+
148
+ lastStreamId uint64
146
149
}
147
150
148
151
var _ = Connector (& Connection {}) // Check compatibility with connector interface.
@@ -528,16 +531,27 @@ func (conn *Connection) dial() (err error) {
528
531
return
529
532
}
530
533
531
- func pack (h * smallWBuf , enc * msgpack.Encoder , reqid uint32 , req Request , res SchemaResolver ) (err error ) {
534
+ func pack (h * smallWBuf , enc * msgpack.Encoder , reqid uint32 ,
535
+ req Request , streamId uint64 , res SchemaResolver ) (err error ) {
532
536
hl := h .Len ()
533
- h .Write ([]byte {
537
+
538
+ hMapLen := byte (0x82 ) // 2 element map.
539
+ if streamId != ignoreStreamId {
540
+ hMapLen = byte (0x83 ) // 3 element map.
541
+ }
542
+ hBytes := []byte {
534
543
0xce , 0 , 0 , 0 , 0 , // Length.
535
- 0x82 , // 2 element map.
544
+ hMapLen ,
536
545
KeyCode , byte (req .Code ()), // Request code.
537
546
KeySync , 0xce ,
538
547
byte (reqid >> 24 ), byte (reqid >> 16 ),
539
548
byte (reqid >> 8 ), byte (reqid ),
540
- })
549
+ }
550
+ if streamId != ignoreStreamId {
551
+ hBytes = append (hBytes , KeyStreamId , byte (streamId ))
552
+ }
553
+
554
+ h .Write (hBytes )
541
555
542
556
if err = req .Body (res , enc ); err != nil {
543
557
return
@@ -555,7 +569,7 @@ func pack(h *smallWBuf, enc *msgpack.Encoder, reqid uint32, req Request, res Sch
555
569
func (conn * Connection ) writeAuthRequest (w * bufio.Writer , scramble []byte ) (err error ) {
556
570
var packet smallWBuf
557
571
req := newAuthRequest (conn .opts .User , string (scramble ))
558
- err = pack (& packet , msgpack .NewEncoder (& packet ), 0 , req , conn .Schema )
572
+ err = pack (& packet , msgpack .NewEncoder (& packet ), 0 , req , ignoreStreamId , conn .Schema )
559
573
560
574
if err != nil {
561
575
return errors .New ("auth: pack error " + err .Error ())
@@ -869,7 +883,7 @@ func (conn *Connection) contextWatchdog(fut *Future, ctx context.Context) {
869
883
}
870
884
}
871
885
872
- func (conn * Connection ) send (req Request ) * Future {
886
+ func (conn * Connection ) send (req Request , streamId uint64 ) * Future {
873
887
fut := conn .newFuture (req .Ctx ())
874
888
if fut .ready == nil {
875
889
return fut
@@ -882,14 +896,14 @@ func (conn *Connection) send(req Request) *Future {
882
896
default :
883
897
}
884
898
}
885
- conn .putFuture (fut , req )
899
+ conn .putFuture (fut , req , streamId )
886
900
if req .Ctx () != nil {
887
901
go conn .contextWatchdog (fut , req .Ctx ())
888
902
}
889
903
return fut
890
904
}
891
905
892
- func (conn * Connection ) putFuture (fut * Future , req Request ) {
906
+ func (conn * Connection ) putFuture (fut * Future , req Request , streamId uint64 ) {
893
907
shardn := fut .requestId & (conn .opts .Concurrency - 1 )
894
908
shard := & conn .shard [shardn ]
895
909
shard .bufmut .Lock ()
@@ -906,7 +920,7 @@ func (conn *Connection) putFuture(fut *Future, req Request) {
906
920
}
907
921
blen := shard .buf .Len ()
908
922
reqid := fut .requestId
909
- if err := pack (& shard .buf , shard .enc , reqid , req , conn .Schema ); err != nil {
923
+ if err := pack (& shard .buf , shard .enc , reqid , req , streamId , conn .Schema ); err != nil {
910
924
shard .buf .Trunc (blen )
911
925
shard .bufmut .Unlock ()
912
926
if f := conn .fetchFuture (reqid ); f == fut {
@@ -1095,7 +1109,7 @@ func (conn *Connection) Do(req Request) *Future {
1095
1109
default :
1096
1110
}
1097
1111
}
1098
- return conn .send (req )
1112
+ return conn .send (req , ignoreStreamId )
1099
1113
}
1100
1114
1101
1115
// ConfiguredTimeout returns a timeout from connection config.
@@ -1121,3 +1135,16 @@ func (conn *Connection) NewPrepared(expr string) (*Prepared, error) {
1121
1135
}
1122
1136
return NewPreparedFromResponse (conn , resp )
1123
1137
}
1138
+
1139
+ // NewStream creates new Stream object for connection.
1140
+ //
1141
+ // Since v. 2.10.0, Tarantool supports streams and interactive transactions over them.
1142
+ // To use interactive transactions, memtx_use_mvcc_engine box option should be set to true.
1143
+ // Since 1.7.0
1144
+ func (conn * Connection ) NewStream () (* Stream , error ) {
1145
+ next := atomic .AddUint64 (& conn .lastStreamId , 1 )
1146
+ return & Stream {
1147
+ Id : next ,
1148
+ Conn : conn ,
1149
+ }, nil
1150
+ }
0 commit comments