1package gocb
2
3import (
4	"encoding/json"
5	"fmt"
6
7	"gopkg.in/couchbase/gocbcore.v7"
8)
9
10// MutationToken holds the mutation state information from an operation.
11type MutationToken struct {
12	token  gocbcore.MutationToken
13	bucket *Bucket
14}
15
16type bucketToken struct {
17	SeqNo  uint64 `json:"seqno"`
18	VbUuid string `json:"vbuuid"`
19}
20
21func (mt bucketToken) MarshalJSON() ([]byte, error) {
22	info := []interface{}{mt.SeqNo, mt.VbUuid}
23	return json.Marshal(info)
24}
25
26func (mt *bucketToken) UnmarshalJSON(data []byte) error {
27	info := []interface{}{&mt.SeqNo, &mt.VbUuid}
28	return json.Unmarshal(data, &info)
29}
30
31type bucketTokens map[string]*bucketToken
32type mutationStateData map[string]*bucketTokens
33
34// MutationState holds and aggregates MutationToken's across multiple operations.
35type MutationState struct {
36	data *mutationStateData
37}
38
39// NewMutationState creates a new MutationState for tracking mutation state.
40func NewMutationState(tokens ...MutationToken) *MutationState {
41	mt := &MutationState{}
42	mt.Add(tokens...)
43	return mt
44}
45
46func (mt *MutationState) addSingle(token MutationToken) {
47	if token.bucket == nil {
48		return
49	}
50
51	if mt.data == nil {
52		data := make(mutationStateData)
53		mt.data = &data
54	}
55
56	bucketName := token.bucket.name
57	if (*mt.data)[bucketName] == nil {
58		tokens := make(bucketTokens)
59		(*mt.data)[bucketName] = &tokens
60	}
61
62	vbId := fmt.Sprintf("%d", token.token.VbId)
63	stateToken := (*(*mt.data)[bucketName])[vbId]
64	if stateToken == nil {
65		stateToken = &bucketToken{}
66		(*(*mt.data)[bucketName])[vbId] = stateToken
67	}
68
69	stateToken.SeqNo = uint64(token.token.SeqNo)
70	stateToken.VbUuid = fmt.Sprintf("%d", token.token.VbUuid)
71}
72
73// Add includes an operation's mutation information in this mutation state.
74func (mt *MutationState) Add(tokens ...MutationToken) {
75	for _, v := range tokens {
76		mt.addSingle(v)
77	}
78}
79
80// MarshalJSON marshal's this mutation state to JSON.
81func (mt *MutationState) MarshalJSON() ([]byte, error) {
82	return json.Marshal(mt.data)
83}
84
85// UnmarshalJSON unmarshal's a mutation state from JSON.
86func (mt *MutationState) UnmarshalJSON(data []byte) error {
87	return json.Unmarshal(data, &mt.data)
88}
89