proto.go 30.5 KB
Newer Older
1
// Copyright (C) 2006-2023  Nexedi SA and Contributors.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.

19 20 21 22 23 24 25 26
// Package proto provides definition of NEO messages and their marshalling
// to/from wire format.
//
// Two NEO nodes can exchange messages over underlying network link after
// performing NEO-specific handshake. A message is sent as a packet specifying
// ID of subconnection multiplexed on top of the underlying link, carried
// message code and message data.
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
27
// PktHeaderN describes packet header structure in 'N' encoding.
28 29 30
//
// Messages are represented by corresponding types that all implement Msg interface.
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
31
// A message type can be looked up by message code with MsgType.
32 33
//
// The proto packages provides only message definitions and low-level
34 35
// primitives for their marshalling. Package lab.nexedi.com/kirr/neo/go/neo/neonet
// provides actual service for message exchange over network.
36
package proto
37

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
38 39
// This file defines everything that relates to messages on the wire.
// In particular every type that is included in a message is defined here as well.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
40 41
//
// By default a structure defined in this file becomes a separate network message.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
42
// If a structure is defined only to represent basic type that is e.g. included in
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
43 44
// several messages and does not itself denote a separate message, its
// definition is prefixed with `//neo:proto typeonly` comment.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
45
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
46
// The order of message definitions is significant - messages are assigned
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
47
// message codes in the same order they are defined.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
48
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
49
// For compatibility with neo/py a message has its code assigned with "answer"
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
50 51
// bit set if either message name starts with "Answer" or message definition is
// prefixed with `//neo:proto answer` comment.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
52 53 54 55 56 57
//
// Packet structure and messages are bit-to-bit compatible with neo/py (see protocol.py).
//
// The code to marshal/unmarshal messages is generated by protogen.go .

//go:generate sh -c "go run protogen.go >zproto-marshal.go"
58
//go:generate gotrace gen .
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
59

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
60

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
61 62 63 64 65
// NOTE for some packets it is possible to decode raw packet -> go version from
// PktBuf in place. E.g. for GetObject.
//
// TODO work this out

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
66
import (
67
	"lab.nexedi.com/kirr/go123/mem"
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
68
	"lab.nexedi.com/kirr/neo/go/zodb"
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
69

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
70
	"lab.nexedi.com/kirr/neo/go/internal/packed"
71

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
72
	"encoding/binary"
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
73
	"errors"
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
74
	"math"
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
75 76
)

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
77
const (
78
	// The protocol version must be increased whenever upgrading a node may require
79
	// to upgrade other nodes.
80
	Version = 0
81

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
82
	// length of packet header in 'N'-encoding
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
83
	PktHeaderLenN = 10 // = unsafe.Sizeof(PktHeaderN{}), but latter gives typed constant (uintptr)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
84

85 86 87
	// packets larger than PktMaxSize are not allowed.
	// this helps to avoid out-of-memory error on packets with corrupt message len.
	PktMaxSize = 0x4000000
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
88

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
89 90
	// answerBit is set in message code in answer messages for compatibility with neo/py
	answerBit = 0x8000
91

Kirill Smelkov's avatar
Kirill Smelkov committed
92
	//INVALID_NID NID = 0
93

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
94 95
	INVALID_TID zodb.Tid = 1<<64 - 1 // 0xffffffffffffffff
	INVALID_OID zodb.Oid = 1<<64 - 1
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
96 97
)

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
98
// PktHeaderN represents header of a raw packet in 'N'-encoding.	XXX unexport?
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
99
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
100 101
// A packet contains connection ID and message.
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
102
//neo:proto typeonly
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
103
type PktHeaderN struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
104 105 106
	ConnId  packed.BE32 // NOTE is .msgid in py
	MsgCode packed.BE16 // payload message code
	MsgLen  packed.BE32 // payload message length (excluding packet header)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
107 108
}

Kirill Smelkov's avatar
Kirill Smelkov committed
109
// Msg is the interface representing a NEO message.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
110 111 112
type Msg interface {
	// marshal/unmarshal into/from wire format:

Kirill Smelkov's avatar
Kirill Smelkov committed
113
	// neoMsgCode returns message code needed to be used for particular message type
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
114
	// on the wire.
Kirill Smelkov's avatar
Kirill Smelkov committed
115
	neoMsgCode() uint16
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
116

Kirill Smelkov's avatar
Kirill Smelkov committed
117 118 119 120 121
	// for encoding E:
	//
	// - neoMsgEncodedLen<E> returns how much space is needed to encode current message payload via E encoding.
	//
	// - neoMsgEncode<E> encodes current message state into buf via E encoding.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
122
	//
Kirill Smelkov's avatar
Kirill Smelkov committed
123 124 125 126 127 128 129 130
	//   len(buf) must be >= neoMsgEncodedLen<E>().
	//
	// - neoMsgDecode<E> decodes data via E encoding into message in-place.

	// N encoding (original struct-based encoding)
	neoMsgEncodedLenN() int
	neoMsgEncodeN(buf []byte)
	neoMsgDecodeN(data []byte) (nread int, err error)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
131

Kirill Smelkov's avatar
Kirill Smelkov committed
132 133 134 135 136 137 138 139 140
	// M encoding (via MessagePack)
	neoMsgEncodedLenM() int
	neoMsgEncodeM(buf []byte)
	neoMsgDecodeM(data []byte) (nread int, err error)
}

// Encoding represents messages encoding.
type Encoding byte

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
141 142
// MsgEncodedLen returns how much space is needed to encode msg payload via encoding e.
func (e Encoding) MsgEncodedLen(msg Msg) int {
Kirill Smelkov's avatar
Kirill Smelkov committed
143 144 145 146 147
	switch e {
	default:   panic("bug")
	case 'N':  return msg.neoMsgEncodedLenN()
	case 'M':  return msg.neoMsgEncodedLenM()
	}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
148 149
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
150
// MsgEncode encodes msg state into buf via encoding e.
Kirill Smelkov's avatar
Kirill Smelkov committed
151
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
152 153
// len(buf) must be >= e.MsgEncodedLen(m).
func (e Encoding) MsgEncode(msg Msg, buf []byte) {
Kirill Smelkov's avatar
Kirill Smelkov committed
154 155 156 157 158 159 160
	switch e {
	default:   panic("bug")
	case 'N':  msg.neoMsgEncodeN(buf)
	case 'M':  msg.neoMsgEncodeM(buf)
	}
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
161 162
// MsgDecode decodes data via encoding e into msg in-place.
func (e Encoding) MsgDecode(msg Msg, data []byte) (nread int, err error) {
Kirill Smelkov's avatar
Kirill Smelkov committed
163 164 165 166 167 168 169 170
	switch e {
	default:   panic("bug")
	case 'N':  return msg.neoMsgDecodeN(data)
	case 'M':  return msg.neoMsgDecodeM(data)
	}
}


Kirill Smelkov's avatar
.  
Kirill Smelkov committed
171
// ErrDecodeOverflow is the error returned by neoMsgDecode when decoding hits buffer overflow
Kirill Smelkov's avatar
Kirill Smelkov committed
172
var ErrDecodeOverflow = errors.New("decode: buffer overflow")
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
173 174 175

// ---- messages ----

Kirill Smelkov's avatar
Kirill Smelkov committed
176
//neo:proto enum
177
type ErrorCode uint32
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
178 179
const (
	ACK ErrorCode = iota
180
	DENIED
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
181 182 183 184 185 186 187 188
	NOT_READY
	OID_NOT_FOUND
	TID_NOT_FOUND
	OID_DOES_NOT_EXIST
	PROTOCOL_ERROR
	REPLICATION_ERROR
	CHECKING_ERROR
	BACKEND_NOT_IMPLEMENTED
189
	NON_READABLE_CELL
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
190
	READ_ONLY_ACCESS
191
	INCOMPLETE_TRANSACTION
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
192 193
)

194
// XXX move this to neo.clusterState wrapping proto.ClusterState?
195 196
//trace:event traceClusterStateChanged(cs *ClusterState)

Kirill Smelkov's avatar
Kirill Smelkov committed
197
//neo:proto enum
198
type ClusterState int8
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
199
const (
200 201 202 203
	// The cluster is initially in the RECOVERING state, and it goes back to
	// this state whenever the partition table becomes non-operational again.
	// An election of the primary master always happens, in case of a network
	// cut between a primary master and all other nodes. The primary master:
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
204 205
	// - first recovers its own data by reading it from storage nodes;
	// - waits for the partition table be operational;
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
206
	// - automatically switch to ClusterVerifying if the cluster can be safely started. XXX not automatic
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
207
	ClusterRecovering ClusterState = iota
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
208 209 210
	// Transient state, used to:
	// - replay the transaction log, in case of unclean shutdown;
	// - and actually truncate the DB if the user asked to do so.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
211
	// Then, the cluster either goes to ClusterRunning or STARTING_BACKUP state.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
212
	ClusterVerifying
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
213
	// Normal operation. The DB is read-writable by clients.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
214
	ClusterRunning
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
215
	// Transient state to shutdown the whole cluster.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
216
	ClusterStopping
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
217 218
	// Transient state, during which the master (re)connect to the upstream
	// master.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
219
	STARTING_BACKUP
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
220 221 222 223
	// Backup operation. The master is notified of new transactions thanks to
	// invalidations and orders storage nodes to fetch them from upstream.
	// Because cells are synchronized independently, the DB is often
	// inconsistent.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
224
	BACKINGUP
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
225 226 227
	// Transient state, when the user decides to go back to RUNNING state.
	// The master stays in this state until the DB is consistent again.
	// In case of failure, the cluster will go back to backup mode.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
228 229 230
	STOPPING_BACKUP
)

Kirill Smelkov's avatar
Kirill Smelkov committed
231
//neo:proto enum
232
type NodeType int8
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
233
const (
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
234
	MASTER NodeType = iota
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
235 236 237 238 239
	STORAGE
	CLIENT
	ADMIN
)

Kirill Smelkov's avatar
Kirill Smelkov committed
240
//neo:proto enum
241
type NodeState int8
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
242
const (
243
	UNKNOWN NodeState = iota //short: U     // XXX tag prefix name ?
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
244
	DOWN                     //short: D
245
	RUNNING                  //short: R
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
246 247 248
	PENDING                  //short: P
)

Kirill Smelkov's avatar
Kirill Smelkov committed
249
//neo:proto enum
250
type CellState int8
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
251
const (
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
252 253 254
	// Write-only cell. Last transactions are missing because storage is/was down
	// for a while, or because it is new for the partition. It usually becomes
	// UP_TO_DATE when replication is done.
255 256 257
	OUT_OF_DATE CellState = iota //short: O    // XXX tag prefix name ?
	// Normal state: cell is writable/readable, and it isn't planned to drop it.
	UP_TO_DATE                   //short: U
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
258 259
	// Same as UP_TO_DATE, except that it will be discarded as soon as another
	// node finishes to replicate it. It means a partition is moved from 1 node
260
	// to another. It is also discarded immediately if out-of-date.
261
	FEEDING                      //short: F
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
262 263
	// A check revealed that data differs from other replicas. Cell is neither
	// readable nor writable.
264 265 266 267
	CORRUPTED                    //short: C
	// Not really a state: only used in network messages to tell storages to drop
	// partitions.
	DISCARDED                    //short: D
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
268 269
)

Kirill Smelkov's avatar
Kirill Smelkov committed
270
// NodeID is a node identifier, 4-bytes signed integer
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
271 272
//
// High-order byte:
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
273 274 275 276 277 278
//
//	7 6 5 4 3 2 1 0
// 	| | | | +-+-+-+-- reserved (0)
// 	| +-+-+---------- node type
// 	+---------------- temporary if negative
//
Kirill Smelkov's avatar
Kirill Smelkov committed
279 280
// NID namespaces are required to prevent conflicts when the master generate
// new nid before it knows nid of existing storage nodes. So only the high
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
281 282 283
// order bit is really important and the 31 other bits could be random.
// Extra namespace information and non-randomness of 3 LOB help to read logs.
//
Kirill Smelkov's avatar
Kirill Smelkov committed
284
// 0 is invalid NodeID	XXX correct?
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
285
//
Kirill Smelkov's avatar
Kirill Smelkov committed
286 287
// TODO -> back to 16-bytes randomly generated node IDs
type NodeID int32
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
288

Kirill Smelkov's avatar
Kirill Smelkov committed
289
// TODO NodeType -> base NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
290

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
291

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
292 293
// Address represents host:port network endpoint.
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
294
//neo:proto typeonly
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
295 296
type Address struct {
	Host string
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
297 298 299 300
	Port uint16
}

// NOTE if Host == "" -> Port not added to wire (see py.PAddress):
Kirill Smelkov's avatar
Kirill Smelkov committed
301
func (a *Address) neoEncodedLenN() int {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
302 303 304 305 306 307 308
	l := string_neoEncodedLen(a.Host)
	if a.Host != "" {
		l += 2
	}
	return l
}

Kirill Smelkov's avatar
Kirill Smelkov committed
309
func (a *Address) neoEncodeN(b []byte) int {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
310 311
	n := string_neoEncode(a.Host, b[0:])
	if a.Host != "" {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
312
		binary.BigEndian.PutUint16(b[n:], a.Port)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
313 314 315 316 317
		n += 2
	}
	return n
}

Kirill Smelkov's avatar
Kirill Smelkov committed
318
func (a *Address) neoDecodeN(b []byte) (uint64, bool) {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
319 320 321 322
	n, ok := string_neoDecode(&a.Host, b)
	if !ok {
		return 0, false
	}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
323
	if a.Host != "" {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
324 325 326 327
		b = b[n:]
		if len(b) < 2 {
			return 0, false
		}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
328
		a.Port = binary.BigEndian.Uint16(b)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
329 330 331 332
		n += 2
	} else {
		a.Port = 0
	}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
333
	return n, true
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
334
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
335

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
336
// Checksum is a SHA1 hash.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
337 338
type Checksum [20]byte

339 340 341 342 343
// Compression is an integer that tells the compression algorithm:
//	0 = no compression algorithm is used
//	1 = zlib is used
type Compression uint8

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
344
// PTid is Partition Table identifier.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
345
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
346
// Zero value means "invalid id" (<-> None in py.PPTID, nil in msgpack)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
347
type PTid uint64
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
348

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
349
// IdTime represents time of identification.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
350 351
type IdTime float64

Kirill Smelkov's avatar
Kirill Smelkov committed
352
func (t IdTime) neoEncodedLenN() int {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
353 354 355
	return 8
}

Kirill Smelkov's avatar
Kirill Smelkov committed
356
func (t IdTime) neoEncodeN(b []byte) int {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
357
	// use -inf as value for no data (NaN != NaN -> hard to use NaN in tests)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
358 359
	// NOTE neo/py uses None for "no data"; we use 0 for "no data" to avoid pointer
	tt := float64(t)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
360
	if tt == math.Inf(-1) {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
361 362 363 364 365 366
		tt = math.NaN()
	}
	float64_neoEncode(b, tt)
	return 8
}

Kirill Smelkov's avatar
Kirill Smelkov committed
367
func (t *IdTime) neoDecodeN(data []byte) (uint64, bool) {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
368 369 370 371 372
	if len(data) < 8 {
		return 0, false
	}
	tt := float64_neoDecode(data)
	if math.IsNaN(tt) {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
373
		tt = math.Inf(-1)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
374 375 376 377
	}
	*t = IdTime(tt)
	return 8, true
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
378

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
379 380
// NodeInfo is information about a node.
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
381
//neo:proto typeonly
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
382
type NodeInfo struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
383 384
	Type   NodeType
	Addr   Address // serving address
Kirill Smelkov's avatar
Kirill Smelkov committed
385
	NID    NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
386
	State  NodeState
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
387
	IdTime IdTime // when this node last identified to master
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
388 389
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
390
//neo:proto typeonly
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
391
type CellInfo struct {
Kirill Smelkov's avatar
Kirill Smelkov committed
392
	NID   NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
393
	State CellState
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
394 395
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
396
//neo:proto typeonly
397
type RowInfo []CellInfo
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
398 399 400 401 402



// Error is a special type of message, because this can be sent against
// any other message, even if such a message does not expect a reply
403
// usually.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
404
//
405
//neo:nodes * -> *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
406
//neo:proto answer
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
407
type Error struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
408
	Code    ErrorCode // PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
409 410 411
	Message string
}

412
// Request a node identification. This must be the first message for any
413 414 415
// connection.
//
//neo:nodes * -> *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
416
type RequestIdentification struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
417
	NodeType    NodeType // XXX name (-> Type)
Kirill Smelkov's avatar
Kirill Smelkov committed
418
	NID         NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
419 420 421
	Address     Address // where requesting node is also accepting connections
	ClusterName string
	IdTime      IdTime
422 423 424
	// storage
	DevPath     []string // [] of devid
	NewNID      []uint32 // [] of PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
425 426
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
427
//neo:proto answer
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
428
type AcceptIdentification struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
429
	NodeType      NodeType // XXX name (-> MyType)
Kirill Smelkov's avatar
Kirill Smelkov committed
430 431
	MyNID         NodeID
	YourNID       NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
432 433
}

434 435 436
// Empty request used as network barrier.
//
//neo:nodes * -> *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
437
type Ping struct{}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
438 439

//neo:proto answer
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
440
type Pong struct{}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
441

442 443 444
// Tell peer that it can close the connection if it has finished with us.
//
//neo:nodes * -> *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
445 446 447
type CloseClient struct {
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
448
// Ask node identifier of the current primary master.
449 450
//
//neo:nodes ctl -> A
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
451 452 453 454
type PrimaryMaster struct {
}

type AnswerPrimary struct {
Kirill Smelkov's avatar
Kirill Smelkov committed
455
	PrimaryNodeID NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
456 457
}

458 459 460 461
// Notify peer that I'm not the primary master. Attach any extra information
// to help the peer joining the cluster.
//
//neo:nodes SM -> *
462
type NotPrimaryMaster struct {
463
	Primary         int32 // index of PM in KnownMasterList
464
	KnownMasterList []Address
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
465 466
}

467 468 469
// Notify information about one or more nodes.
//
//neo:nodes M -> *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
470
type NotifyNodeInformation struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
471
	// NOTE in py this is monotonic_time() of call to broadcastNodesInformation() & friends
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
472 473
	IdTime   IdTime
	NodeList []NodeInfo
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
474 475
}

476 477 478 479
// Ask storage nodes data needed by master to recover.
// Reused by `neoctl print ids`.
//
//neo:nodes M -> S; ctl -> A -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
480 481 482 483 484
type Recovery struct {
}

type AnswerRecovery struct {
	PTid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
485 486
	BackupTid   zodb.Tid
	TruncateTid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
487 488 489
}

// Ask the last OID/TID so that a master can initialize its TransactionManager.
490 491 492
// Reused by `neoctl print ids`.
//
//neo:nodes M -> S; ctl -> A -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
493 494 495 496
type LastIDs struct {
}

type AnswerLastIDs struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
497 498
	LastOid zodb.Oid
	LastTid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
499 500
}

501 502
// Ask storage node the remaining data needed by master to recover.
//
503
//neo:nodes M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
504
type AskPartitionTable struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
505 506 507
}

type AnswerPartitionTable struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
508
	PTid
509 510
	NumReplicas uint32	// PNumber
	RowList     []RowInfo
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
511 512
}

513
// Send the full partition table to admin/client/storage nodes on connection.
514
//
515
//neo:nodes M -> A, C, S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
516
type SendPartitionTable struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
517
	PTid
518 519
	NumReplicas uint32	// PNumber
	RowList     []RowInfo
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
520 521
}

522 523 524
// Notify about changes in the partition table.
//
//neo:nodes M -> *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
525
type NotifyPartitionChanges struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
526
	PTid
527 528
	NumReplicas uint32 // PNumber
	CellList    []struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
529 530
		Offset   uint32 // PNumber	XXX -> Pid
		CellInfo CellInfo
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
531
	}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
532 533
}

534 535 536 537
// Tell a storage node to start operation. Before this message, it must only
// communicate with the primary master.
//
//neo:nodes M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
538
type StartOperation struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
539 540 541
	// XXX: Is this boolean needed ? Maybe this
	//      can be deduced from cluster state.
	Backup bool
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
542 543
}

544 545 546 547
// Notify that the cluster is not operational anymore. Any operation between
// nodes must be aborted.
//
//neo:nodes M -> S, C
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
548 549 550
type StopOperation struct {
}

551 552 553
// Ask unfinished transactions, which will be replicated when they're finished.
//
//neo:nodes S -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
554
type UnfinishedTransactions struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
555 556
	RowList []struct {
		Offset uint32 // PNumber	XXX -> Pid
557
	}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
558 559 560
}

type AnswerUnfinishedTransactions struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
561
	MaxTID  zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
562
	TidList []struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
563
		UnfinishedTID zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
564 565 566
	}
}

567 568 569 570
// Ask locked transactions to replay committed transactions that haven't been
// unlocked.
//
//neo:nodes M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
571 572 573 574
type LockedTransactions struct {
}

type AnswerLockedTransactions struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
575
	TidDict map[zodb.Tid]zodb.Tid // ttid -> tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
576 577
}

578 579 580 581
// Return final tid if ttid has been committed, to recover from certain
// failures during tpc_finish.
//
//neo:nodes M -> S; C -> M, S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
582
type FinalTID struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
583
	TTID zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
584 585 586
}

type AnswerFinalTID struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
587
	Tid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
588 589
}

590 591 592
// Do replay a committed transaction that was not unlocked.
//
//neo:nodes M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
593
type ValidateTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
594 595
	TTID zodb.Tid
	Tid  zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
596 597 598
}


599 600 601
// Ask to begin a new transaction. This maps to `tpc_begin`.
//
//neo:nodes C -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
602
type BeginTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
603
	Tid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
604 605 606
}

type AnswerBeginTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
607
	Tid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
608 609
}

610

611
// Report storage nodes for which vote failed.
612
// True is returned if it's still possible to finish the transaction.
613 614
//
//neo:nodes C -> M
615
type FailedVote struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
616
	Tid      zodb.Tid
Kirill Smelkov's avatar
Kirill Smelkov committed
617
	NodeList []NodeID
618

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
619
	// answer = Error
620 621
}

622 623 624 625
// Finish a transaction. Return the TID of the committed transaction.
// This maps to `tpc_finish`.
//
//neo:nodes C -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
626
type FinishTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
627
	Tid         zodb.Tid // XXX this is ttid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
628 629
	OIDList     []zodb.Oid
	CheckedList []zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
630 631
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
632
type AnswerTransactionFinished struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
633 634
	TTid zodb.Tid
	Tid  zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
635 636
}

637 638 639
// Commit a transaction. The new data is read-locked.
//
//neo:nodes M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
640
type LockInformation struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
641 642
	Ttid zodb.Tid
	Tid  zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
643 644
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
645
type AnswerInformationLocked struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
646
	Ttid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
647 648
}

649 650 651 652
// Notify about a new transaction modifying objects,
// invalidating client caches.
//
//neo:nodes M -> C
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
653
type InvalidateObjects struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
654 655
	Tid     zodb.Tid
	OidList []zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
656 657
}

658 659 660 661
// Notify about a successfully committed transaction. The new data can be
// unlocked.
//
//neo:nodes M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
662 663
// XXX -> InformationUnlocked?
type NotifyUnlockInformation struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
664
	TTID zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
665 666
}

667 668 669
// Ask new OIDs to create objects.
//
//neo:nodes C -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
670
type AskNewOIDs struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
671
	NumOIDs uint32 // PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
672 673
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
674
type AnswerNewOIDs struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
675
	OidList []zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
676 677 678
}


679 680 681 682
// Ask master to generate a new TTID that will be used by the client to solve
// a deadlock by rebasing the transaction on top of concurrent changes.
//
//neo:nodes S -> M -> C
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
683 684
// XXX -> Deadlocked?
type NotifyDeadlock struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
685 686
	TTid       zodb.Tid
	LockingTid zodb.Tid
687 688
}

689 690 691
// Rebase a transaction to solve a deadlock.
//
//neo:nodes C -> S
692
type RebaseTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
693 694
	TTid       zodb.Tid
	LockingTid zodb.Tid
695 696 697
}

type AnswerRebaseTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
698
	OidList []zodb.Oid
699 700
}

701 702 703
// Rebase an object change to solve a deadlock.
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
704 705 706 707 708
//
// XXX: It is a request packet to simplify the implementation. For more
//      efficiency, this should be turned into a notification, and the
//      RebaseTransaction should answered once all objects are rebased
//      (so that the client can still wait on something).
709
type RebaseObject struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
710 711
	TTid zodb.Tid
	Oid  zodb.Oid
712 713 714 715
}

type AnswerRebaseObject struct {
	// FIXME POption('conflict')
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
716 717
	Serial         zodb.Tid
	ConflictSerial zodb.Tid
718
	// FIXME POption('data')
719
		Compression Compression
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
720 721
		Checksum    Checksum
		Data        *mem.Buf
722 723 724
}


725 726
// Ask to create/modify an object. This maps to `store`.
//
727
// As for IStorage, 'serial' is ZERO_TID for new objects.
728 729
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
730
type StoreObject struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
731 732
	Oid         zodb.Oid
	Serial      zodb.Tid
733
	Compression Compression
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
734 735 736 737
	Checksum    Checksum
	Data        []byte // TODO -> msg.Buf, separately (for writev)
	DataSerial  zodb.Tid
	Tid         zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
738 739 740
}

type AnswerStoreObject struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
741
	Conflict zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
742 743
}

744 745 746
// Abort a transaction. This maps to `tpc_abort`.
//
//neo:nodes C -> S; C -> M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
747
type AbortTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
748
	Tid      zodb.Tid
Kirill Smelkov's avatar
Kirill Smelkov committed
749
	NodeList []NodeID // unused for * -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
750 751
}

752 753 754
// Ask to store a transaction. Implies vote.
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
755
type StoreTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
756 757 758 759 760
	Tid         zodb.Tid
	User        string
	Description string
	Extension   string
	OidList     []zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
761 762
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
763
type AnswerStoreTransaction struct{}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
764

765 766 767
// Ask to vote a transaction.
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
768
type VoteTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
769
	Tid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
770 771
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
772
type AnswerVoteTransaction struct{}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
773

774 775 776 777
// Ask a stored object by its OID, optionally at/before a specific tid.
// This maps to `load/loadBefore/loadSerial`.
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
778
type GetObject struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
779
	Oid    zodb.Oid
780 781
	At     zodb.Tid
	Before zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
782 783
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
784
type AnswerObject struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
785 786 787
	Oid         zodb.Oid
	Serial      zodb.Tid
	NextSerial  zodb.Tid
788
	Compression Compression
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
789 790 791
	Checksum    Checksum
	Data        *mem.Buf // TODO encode -> separately (for writev)
	DataSerial  zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
792 793 794
}

// Ask for TIDs between a range of offsets. The order of TIDs is descending,
795 796 797
// and the range is [first, last). This maps to `undoLog`.
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
798
type AskTIDs struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
799 800
	First     uint64 // PIndex       [first, last) are offsets that define
	Last      uint64 // PIndex       range in tid list on remote.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
801
	Partition uint32 // PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
802 803
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
804
type AnswerTIDs struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
805
	TIDList []zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
806 807
}

808 809 810
// Ask for transaction metadata.
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
811
type TransactionInformation struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
812
	Tid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
813 814 815
}

type AnswerTransactionInformation struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
816 817 818 819 820 821
	Tid         zodb.Tid
	User        string
	Description string
	Extension   string
	Packed      bool
	OidList     []zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
822 823 824
}

// Ask history information for a given object. The order of serials is
825 826 827
// descending, and the range is [first, last]. This maps to `history`.
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
828
type ObjectHistory struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
829
	Oid   zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
830 831
	First uint64 // PIndex
	Last  uint64 // PIndex
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
832 833 834
}

type AnswerObjectHistory struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
835
	Oid         zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
836
	HistoryList []struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
837 838
		Serial zodb.Tid
		Size   uint32 // PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
839 840 841
	}
}

842 843 844
// Ask information about partitions.
//
//neo:nodes ctl -> A
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
845
type PartitionList struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
846 847
	MinOffset uint32 // PNumber
	MaxOffset uint32 // PNumber
Kirill Smelkov's avatar
Kirill Smelkov committed
848
	NodeID    NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
849 850 851 852
}

type AnswerPartitionList struct {
	PTid
853 854
	NumReplicas uint32 // PNumber
	RowList     []RowInfo
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
855 856
}

857
// Ask information about nodes.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
858
//
859
//neo:nodes ctl -> A
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
860
type NodeList struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
861
	NodeType
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
862 863 864
}

type AnswerNodeList struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
865
	NodeList []NodeInfo
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
866 867
}

868 869 870
// Change the state of a node.
//
//neo:nodes ctl -> A -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
871
type SetNodeState struct {
Kirill Smelkov's avatar
Kirill Smelkov committed
872
	NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
873
	NodeState
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
874

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
875
	// answer = Error
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
876 877
}

878 879 880 881
// Mark given pending nodes as running, for future inclusion when tweaking
// the partition table.
//
//neo:nodes ctl -> A -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
882
type AddPendingNodes struct {
Kirill Smelkov's avatar
Kirill Smelkov committed
883
	NodeList []NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
884

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
885
	// answer = Error
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
886 887
}

888 889 890 891
// Ask the master to balance the partition table, optionally excluding
// specific nodes in anticipation of removing them.
//
//neo:nodes ctl -> A -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
892
type TweakPartitionTable struct {
893
	DryRun   bool
Kirill Smelkov's avatar
Kirill Smelkov committed
894
	NodeList []NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
895

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
896
	// answer = Error
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
897 898
}

899 900 901 902 903
type AnswerTweakPartitionTable struct {
	Changed  bool
	RowList  []RowInfo
}

904 905 906 907 908 909 910
// Set the number of replicas.
//
//neo:nodes ctl -> A -> M
type SetNumReplicas struct {
	NumReplicas uint32 // PNumber
}

911 912 913
// Set the cluster state.
//
//neo:nodes ctl -> A -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
914
type SetClusterState struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
915
	State ClusterState
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
916

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
917
	// answer = Error
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
918 919
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
920
//neo:proto typeonly
921
type repairFlags struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
922
	DryRun bool
923 924
	// pruneOrphan bool

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
925
	// answer = Error
926 927
}

928 929 930
// Ask storage nodes to repair their databases.
//
//neo:nodes ctl -> A -> M
931
type Repair struct {
Kirill Smelkov's avatar
Kirill Smelkov committed
932
	NodeList []NodeID
933 934 935
	repairFlags
}

936 937 938 939
// Repair is translated to this message, asking a specific storage node to
// repair its database.
//
//neo:nodes M -> S
940 941 942 943
type RepairOne struct {
	repairFlags
}

944 945 946
// Notify about a cluster state change.
//
//neo:nodes M -> *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
947
type NotifyClusterState struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
948
	State ClusterState
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
949 950
}

951 952 953
// Ask the state of the cluster
//
//neo:nodes ctl -> A; A -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
954 955 956 957
type AskClusterState struct {
}

type AnswerClusterState struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
958
	State ClusterState
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
959 960 961 962 963
}


// Ask storage the serial where object data is when undoing given transaction,
// for a list of OIDs.
964
//
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
965 966 967 968 969 970 971 972 973
// object_tid_dict has the following format:
//     key: oid
//     value: 3-tuple
//         current_serial (TID)
//             The latest serial visible to the undoing transaction.
//         undo_serial (TID)
//             Where undone data is (tid at which data is before given undo).
//         is_current (bool)
//             If current_serial's data is current on storage.
974 975
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
976
type ObjectUndoSerial struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
977 978 979 980
	Tid       zodb.Tid
	LTID      zodb.Tid
	UndoneTID zodb.Tid
	OidList   []zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
981 982 983
}

type AnswerObjectUndoSerial struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
984
	ObjectTIDDict map[zodb.Oid]struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
985 986 987
		CurrentSerial zodb.Tid
		UndoSerial    zodb.Tid
		IsCurrent     bool
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
988 989 990
	}
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
991
// Ask for length TIDs starting at min_tid. The order of TIDs is ascending.
992 993 994
// Used by `iterator`.
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
995
type AskTIDsFrom struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
996 997 998 999
	MinTID    zodb.Tid
	MaxTID    zodb.Tid
	Length    uint32 // PNumber
	Partition uint32 // PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1000 1001 1002 1003 1004
}

type AnswerTIDsFrom struct {
	TidList []zodb.Tid
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1005

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1006

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1007
// Request a pack at given TID.
1008 1009
//
//neo:nodes C -> M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1010
type Pack struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1011
	Tid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1012 1013 1014
}

type AnswerPack struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1015
	Status bool
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1016 1017 1018
}


1019 1020 1021 1022
// Ask the cluster to search for mismatches between replicas, metadata only,
// and optionally within a specific range. Reference nodes can be specified.
//
//neo:nodes ctl -> A -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1023
type CheckReplicas struct {
Kirill Smelkov's avatar
Kirill Smelkov committed
1024
	PartitionDict map[uint32]NodeID // partition -> source	(PNumber)
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1025 1026
	MinTID        zodb.Tid
	MaxTID        zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1027

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1028
	// answer = Error
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1029 1030
}

1031 1032 1033 1034 1035
// Ask a storage node to compare a partition with all other nodes.
// Like for CheckReplicas, only metadata are checked, optionally within a
// specific range. A reference node can be specified.
//
//neo:nodes M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1036
type CheckPartition struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1037
	Partition uint32 // PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1038 1039 1040 1041
	Source    struct {
		UpstreamName string
		Address      Address
	}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1042 1043
	MinTID zodb.Tid
	MaxTID zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1044 1045 1046 1047 1048 1049
}


// Ask some stats about a range of transactions.
// Used to know if there are differences between a replicating node and
// reference node.
1050 1051
//
//neo:nodes S -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1052
type CheckTIDRange struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1053 1054
	Partition uint32 // PNumber
	Length    uint32 // PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1055 1056
	MinTID    zodb.Tid
	MaxTID    zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1057 1058 1059
}

type AnswerCheckTIDRange struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1060
	Count    uint32 // PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1061
	Checksum Checksum
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1062
	MaxTID   zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1063 1064 1065 1066 1067
}

// Ask some stats about a range of object history.
// Used to know if there are differences between a replicating node and
// reference node.
1068 1069
//
//neo:nodes S -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1070
type CheckSerialRange struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1071 1072 1073 1074 1075
	Partition uint32 // PNumber
	Length    uint32 // PNumber
	MinTID    zodb.Tid
	MaxTID    zodb.Tid
	MinOID    zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1076 1077 1078
}

type AnswerCheckSerialRange struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1079 1080 1081 1082 1083
	Count       uint32 // PNumber
	TidChecksum Checksum
	MaxTID      zodb.Tid
	OidChecksum Checksum
	MaxOID      zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1084 1085
}

1086 1087 1088
// Notify that mismatches were found while check replicas for a partition.
//
//neo:nodes S -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1089
type PartitionCorrupted struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1090
	Partition uint32 // PNumber
Kirill Smelkov's avatar
Kirill Smelkov committed
1091
	CellList  []NodeID
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1092 1093
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1094
// Notify that node is ready to serve requests.
1095 1096
//
//neo:nodes S -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1097 1098 1099
type NotifyReady struct {
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1100 1101

// Ask last committed TID.
1102 1103
//
//neo:nodes C -> M; ctl -> A -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1104 1105 1106 1107
type LastTransaction struct {
}

type AnswerLastTransaction struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1108
	Tid zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1109 1110
}

1111 1112 1113 1114 1115
// Check if given serial is current for the given oid, and lock it so that
// this state is not altered until transaction ends.
// This maps to `checkCurrentSerialInTransaction`.
//
//neo:nodes C -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1116
type CheckCurrentSerial struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1117 1118 1119
	Tid    zodb.Tid
	Oid    zodb.Oid
	Serial zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1120
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1121

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1122 1123 1124 1125 1126 1127
type AnswerCheckCurrentSerial struct {
	// was _answer = StoreObject._answer in py
	// XXX can we do without embedding e.g. `type AnswerCheckCurrentSerial AnswerStoreObject` ?
	AnswerStoreObject
}

1128 1129 1130
// Notify that a transaction blocking a replication is now finished.
//
//neo:nodes M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1131
type NotifyTransactionFinished struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1132 1133
	TTID   zodb.Tid
	MaxTID zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1134 1135
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1136

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1137 1138
// replication

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1139 1140 1141 1142 1143 1144
// Notify a storage node to replicate partitions up to given 'tid'
// and from given sources.
//
// - upstream_name: replicate from an upstream cluster
// - address: address of the source storage node, or None if there's no new
//            data up to 'tid' for the given partition
1145 1146
//
//neo:nodes M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1147
type Replicate struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1148
	Tid          zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1149
	UpstreamName string
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1150
	SourceDict   map[uint32/*PNumber*/]string // partition -> address	FIXME string -> Address
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1151 1152 1153 1154
}

// Notify the master node that a partition has been successfully replicated
// from a storage to another.
1155 1156
//
//neo:nodes S -> M
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1157
type ReplicationDone struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1158 1159
	Offset uint32 // PNumber
	Tid    zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1160
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1161

1162 1163 1164 1165
// Ask a storage node to send all transaction data we don't have,
// and reply with the list of transactions we should not have.
//
//neo:nodes S -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1166
type FetchTransactions struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1167 1168 1169
	Partition    uint32 // PNumber
	Length       uint32 // PNumber
	MinTid       zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1170
	MaxTid       zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1171
	TxnKnownList []zodb.Tid // already known transactions
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1172 1173 1174 1175 1176
}

type AnswerFetchTransactions struct {
	PackTid       zodb.Tid
	NextTid       zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1177
	TxnDeleteList []zodb.Tid // transactions to delete
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1178 1179
}

1180 1181 1182 1183
// Ask a storage node to send object records we don't have,
// and reply with the list of records we should not have.
//
//neo:nodes S -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1184
type FetchObjects struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1185 1186
	Partition uint32 // PNumber
	Length    uint32 // PNumber
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1187
	MinTid    zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1188
	MaxTid    zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1189 1190 1191
	MinOid    zodb.Oid

	// already known objects
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1192
	ObjKnownDict map[zodb.Tid][]zodb.Oid // serial -> []oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1193 1194
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1195
type AnswerFetchObjects struct {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1196 1197 1198
	PackTid zodb.Tid
	NextTid zodb.Tid
	NextOid zodb.Oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1199 1200

	// objects to delete
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1201
	ObjDeleteDict map[zodb.Tid][]zodb.Oid // serial -> []oid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1202
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1203

1204 1205 1206
// Send metadata of a transaction to a node that do not have them.
//
//neo:nodes S -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1207 1208
type AddTransaction struct {
	Tid         zodb.Tid
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1209
	User        string
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1210 1211 1212 1213 1214 1215
	Description string
	Extension   string
	Packed      bool
	TTid        zodb.Tid
	OidList     []zodb.Oid
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1216

1217 1218 1219
// Send an object record to a node that do not have it.
//
//neo:nodes S -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1220 1221 1222
type AddObject struct {
	Oid         zodb.Oid
	Serial      zodb.Tid
1223
	Compression Compression
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1224
	Checksum    Checksum
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1225
	Data        *mem.Buf
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1226 1227
	DataSerial  zodb.Tid
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1228 1229

// Request DB to be truncated. Also used to leave backup mode.
1230 1231
//
//neo:nodes ctl -> A -> M; M -> S
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1232 1233 1234
type Truncate struct {
	Tid zodb.Tid

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1235
	// answer = Error
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1236
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1237

1238 1239 1240 1241 1242 1243
// Request all nodes to flush their logs.
//
//neo:nodes ctl -> A -> M -> *
type FlushLog struct {}


Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1244 1245
// ---- runtime support for protogen and custom codecs ----

Kirill Smelkov's avatar
Kirill Smelkov committed
1246
// customCodecN is the interface that is implemented by types with custom N encodings.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1247 1248
//
// its semantic is very similar to Msg.
Kirill Smelkov's avatar
Kirill Smelkov committed
1249 1250 1251 1252
type customCodecN interface {
	neoEncodedLenN() int
	neoEncodeN(buf []byte) (nwrote int)
	neoDecodeN(data []byte) (nread uint64, ok bool) // XXX uint64 or int here?
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1253
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268

func byte2bool(b byte) bool {
	return b != 0
}

func bool2byte(b bool) byte {
	if b {
		return 1
	} else {
		return 0
	}
}

// NOTE py.None encodes as '\xff' * 8	(-> we use NaN for None)
// NOTE '\xff' * 8 represents FP NaN but many other NaN bits representations exist
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1269
func float64_neoEncode(b []byte, f float64) {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280
	var fu uint64
	if !math.IsNaN(f) {
		fu = math.Float64bits(f)
	} else {
		// convert all NaNs to canonical \xff * 8
		fu = 1<<64 - 1
	}

	binary.BigEndian.PutUint64(b, fu)
}

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1281
func float64_neoDecode(b []byte) float64 {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1282 1283 1284
	fu := binary.BigEndian.Uint64(b)
	return math.Float64frombits(fu)
}
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300


// XXX we need string_neo* only for Address
// XXX dup of genSlice1 in protogen.go

func string_neoEncodedLen(s string) int {
	return 4 + len(s)
}

func string_neoEncode(s string, data []byte) int {
	l := len(s)
	binary.BigEndian.PutUint32(data, uint32(l))
	copy(data[4:4+l], s) // NOTE [:l] to catch data overflow as copy copies minimal len
	return 4 + l
}

1301
func string_neoDecode(sp *string, data []byte) (nread uint64, ok bool) {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1302 1303 1304 1305 1306
	if len(data) < 4 {
		return 0, false
	}
	l := binary.BigEndian.Uint32(data)
	data = data[4:]
1307
	if uint64(len(data)) < uint64(l) {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1308 1309 1310 1311
		return 0, false
	}

	*sp = string(data[:l])
1312
	return 4 + uint64(l), true
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
1313
}