Merge pull request #47 from anytypeio/update-proto

This commit is contained in:
Mikhail Rakhmanov 2023-03-11 13:48:57 +01:00 committed by GitHub
commit 1fbf87995b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1189 additions and 435 deletions

120
app/ocache/entry.go Normal file
View File

@ -0,0 +1,120 @@
package ocache
import (
"context"
"go.uber.org/zap"
"sync"
"time"
)
type entryState int
const (
entryStateLoading = iota
entryStateActive
entryStateClosing
entryStateClosed
)
type entry struct {
id string
state entryState
lastUsage time.Time
load chan struct{}
loadErr error
value Object
close chan struct{}
mx sync.Mutex
}
func newEntry(id string, value Object, state entryState) *entry {
return &entry{
id: id,
load: make(chan struct{}),
lastUsage: time.Now(),
state: state,
value: value,
}
}
func (e *entry) isActive() bool {
e.mx.Lock()
defer e.mx.Unlock()
return e.state == entryStateActive
}
func (e *entry) isClosing() bool {
e.mx.Lock()
defer e.mx.Unlock()
return e.state == entryStateClosed || e.state == entryStateClosing
}
func (e *entry) waitLoad(ctx context.Context, id string) (value Object, err error) {
select {
case <-ctx.Done():
log.DebugCtx(ctx, "ctx done while waiting on object load", zap.String("id", id))
return nil, ctx.Err()
case <-e.load:
return e.value, e.loadErr
}
}
func (e *entry) waitClose(ctx context.Context, id string) (res bool, err error) {
e.mx.Lock()
switch e.state {
case entryStateClosing:
waitCh := e.close
e.mx.Unlock()
select {
case <-ctx.Done():
log.DebugCtx(ctx, "ctx done while waiting on object close", zap.String("id", id))
return false, ctx.Err()
case <-waitCh:
return true, nil
}
case entryStateClosed:
e.mx.Unlock()
return true, nil
default:
e.mx.Unlock()
return false, nil
}
}
func (e *entry) setClosing(wait bool) (prevState, curState entryState) {
e.mx.Lock()
prevState = e.state
curState = e.state
if e.state == entryStateClosing {
waitCh := e.close
e.mx.Unlock()
if !wait {
return
}
<-waitCh
e.mx.Lock()
}
if e.state != entryStateClosed {
e.state = entryStateClosing
e.close = make(chan struct{})
}
curState = e.state
e.mx.Unlock()
return
}
func (e *entry) setActive(chClose bool) {
e.mx.Lock()
defer e.mx.Unlock()
if chClose {
close(e.close)
}
e.state = entryStateActive
}
func (e *entry) setClosed() {
e.mx.Lock()
defer e.mx.Unlock()
close(e.close)
e.state = entryStateClosed
}

View File

@ -44,12 +44,6 @@ var WithGCPeriod = func(gcPeriod time.Duration) Option {
} }
} }
var WithRefCounter = func(enable bool) Option {
return func(cache *oCache) {
cache.refCounter = enable
}
}
func New(loadFunc LoadFunc, opts ...Option) OCache { func New(loadFunc LoadFunc, opts ...Option) OCache {
c := &oCache{ c := &oCache{
data: make(map[string]*entry), data: make(map[string]*entry),
@ -73,33 +67,7 @@ func New(loadFunc LoadFunc, opts ...Option) OCache {
type Object interface { type Object interface {
Close() (err error) Close() (err error)
} TryClose(objectTTL time.Duration) (res bool, err error)
type ObjectLocker interface {
Object
Locked() bool
}
type ObjectLastUsage interface {
LastUsage() time.Time
}
type entry struct {
id string
lastUsage time.Time
refCount uint32
isClosing bool
load chan struct{}
loadErr error
value Object
close chan struct{}
}
func (e *entry) locked() bool {
if locker, ok := e.value.(ObjectLocker); ok {
return locker.Locked()
}
return false
} }
type OCache interface { type OCache interface {
@ -116,12 +84,8 @@ type OCache interface {
// Add adds new object to cache // Add adds new object to cache
// Returns error when object exists // Returns error when object exists
Add(id string, value Object) (err error) Add(id string, value Object) (err error)
// Release decreases the refs counter
Release(id string) bool
// Reset sets refs counter to 0
Reset(id string) bool
// Remove closes and removes object // Remove closes and removes object
Remove(id string) (ok bool, err error) Remove(ctx context.Context, id string) (ok bool, err error)
// ForEach iterates over all loaded objects, breaks when callback returns false // ForEach iterates over all loaded objects, breaks when callback returns false
ForEach(f func(v Object) (isContinue bool)) ForEach(f func(v Object) (isContinue bool))
// GC frees not used and expired objects // GC frees not used and expired objects
@ -134,17 +98,16 @@ type OCache interface {
} }
type oCache struct { type oCache struct {
mu sync.Mutex mu sync.Mutex
data map[string]*entry data map[string]*entry
loadFunc LoadFunc loadFunc LoadFunc
timeNow func() time.Time timeNow func() time.Time
ttl time.Duration ttl time.Duration
gc time.Duration gc time.Duration
closed bool closed bool
closeCh chan struct{} closeCh chan struct{}
log *zap.SugaredLogger log *zap.SugaredLogger
metrics *metrics metrics *metrics
refCounter bool
} }
func (c *oCache) Get(ctx context.Context, id string) (value Object, err error) { func (c *oCache) Get(ctx context.Context, id string) (value Object, err error) {
@ -160,69 +123,36 @@ Load:
return nil, ErrClosed return nil, ErrClosed
} }
if e, ok = c.data[id]; !ok { if e, ok = c.data[id]; !ok {
e = newEntry(id, nil, entryStateLoading)
load = true load = true
e = &entry{
id: id,
load: make(chan struct{}),
}
c.data[id] = e c.data[id] = e
} }
closing := e.isClosing e.lastUsage = time.Now()
if !e.isClosing {
e.lastUsage = c.timeNow()
if c.refCounter {
e.refCount++
}
}
c.mu.Unlock() c.mu.Unlock()
if closing { reload, err := e.waitClose(ctx, id)
select { if err != nil {
case <-ctx.Done(): return nil, err
log.DebugCtx(ctx, "ctx done while waiting on object close", zap.String("id", id)) }
return nil, ctx.Err() if reload {
case <-e.close: goto Load
goto Load
}
} }
if load { if load {
go c.load(ctx, id, e) go c.load(ctx, id, e)
} }
if c.metrics != nil { c.metricsGet(!load)
if load { return e.waitLoad(ctx, id)
c.metrics.miss.Inc()
} else {
c.metrics.hit.Inc()
}
}
select {
case <-ctx.Done():
log.DebugCtx(ctx, "ctx done while waiting on object load", zap.String("id", id))
return nil, ctx.Err()
case <-e.load:
}
return e.value, e.loadErr
} }
func (c *oCache) Pick(ctx context.Context, id string) (value Object, err error) { func (c *oCache) Pick(ctx context.Context, id string) (value Object, err error) {
c.mu.Lock() c.mu.Lock()
val, ok := c.data[id] val, ok := c.data[id]
if !ok || val.isClosing { if !ok || val.isClosing() {
c.mu.Unlock() c.mu.Unlock()
return nil, ErrNotExists return nil, ErrNotExists
} }
c.mu.Unlock() c.mu.Unlock()
c.metricsGet(true)
if c.metrics != nil { return val.waitLoad(ctx, id)
c.metrics.hit.Inc()
}
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-val.load:
return val.value, val.loadErr
}
} }
func (c *oCache) load(ctx context.Context, id string, e *entry) { func (c *oCache) load(ctx context.Context, id string, e *entry) {
@ -236,63 +166,39 @@ func (c *oCache) load(ctx context.Context, id string, e *entry) {
delete(c.data, id) delete(c.data, id)
} else { } else {
e.value = value e.value = value
e.setActive(false)
} }
} }
func (c *oCache) Release(id string) bool { func (c *oCache) Remove(ctx context.Context, id string) (ok bool, err error) {
c.mu.Lock()
defer c.mu.Unlock()
if c.closed {
return false
}
if e, ok := c.data[id]; ok {
if c.refCounter && e.refCount > 0 {
e.refCount--
return true
}
}
return false
}
func (c *oCache) Reset(id string) bool {
c.mu.Lock()
defer c.mu.Unlock()
if c.closed {
return false
}
if e, ok := c.data[id]; ok {
e.refCount = 0
return true
}
return false
}
func (c *oCache) Remove(id string) (ok bool, err error) {
c.mu.Lock() c.mu.Lock()
if c.closed { if c.closed {
c.mu.Unlock() c.mu.Unlock()
err = ErrClosed err = ErrClosed
return return
} }
var e *entry e, ok := c.data[id]
e, ok = c.data[id] if !ok {
if !ok || e.isClosing {
c.mu.Unlock() c.mu.Unlock()
return return false, ErrNotExists
} }
e.isClosing = true
e.close = make(chan struct{})
c.mu.Unlock() c.mu.Unlock()
return c.remove(ctx, e)
}
<-e.load func (c *oCache) remove(ctx context.Context, e *entry) (ok bool, err error) {
if e.value != nil { if _, err = e.waitLoad(ctx, e.id); err != nil {
return false, err
}
_, curState := e.setClosing(true)
if curState == entryStateClosing {
ok = true
err = e.value.Close() err = e.value.Close()
c.mu.Lock()
e.setClosed()
delete(c.data, e.id)
c.mu.Unlock()
} }
c.mu.Lock()
close(e.close)
delete(c.data, e.id)
c.mu.Unlock()
return return
} }
@ -314,13 +220,7 @@ func (c *oCache) Add(id string, value Object) (err error) {
if _, ok := c.data[id]; ok { if _, ok := c.data[id]; ok {
return ErrExists return ErrExists
} }
e := &entry{ e := newEntry(id, value, entryStateActive)
id: id,
lastUsage: time.Now(),
refCount: 0,
load: make(chan struct{}),
value: value,
}
close(e.load) close(e.load)
c.data[id] = e c.data[id] = e
return return
@ -332,7 +232,7 @@ func (c *oCache) ForEach(f func(obj Object) (isContinue bool)) {
for _, v := range c.data { for _, v := range c.data {
select { select {
case <-v.load: case <-v.load:
if v.value != nil && !v.isClosing { if v.value != nil && !v.isClosing() {
objects = append(objects, v.value) objects = append(objects, v.value)
} }
default: default:
@ -368,40 +268,35 @@ func (c *oCache) GC() {
deadline := c.timeNow().Add(-c.ttl) deadline := c.timeNow().Add(-c.ttl)
var toClose []*entry var toClose []*entry
for _, e := range c.data { for _, e := range c.data {
if e.isClosing { if e.isActive() && e.lastUsage.Before(deadline) {
continue
}
lu := e.lastUsage
if lug, ok := e.value.(ObjectLastUsage); ok {
lu = lug.LastUsage()
}
if !e.locked() && e.refCount <= 0 && lu.Before(deadline) {
e.isClosing = true
e.close = make(chan struct{}) e.close = make(chan struct{})
toClose = append(toClose, e) toClose = append(toClose, e)
} }
} }
size := len(c.data) size := len(c.data)
c.mu.Unlock() c.mu.Unlock()
closedNum := 0
for _, e := range toClose { for _, e := range toClose {
<-e.load prevState, _ := e.setClosing(false)
if e.value != nil { if prevState == entryStateClosing || prevState == entryStateClosed {
if err := e.value.Close(); err != nil { continue
c.log.With("object_id", e.id).Warnf("GC: object close error: %v", err) }
} closed, err := e.value.TryClose(c.ttl)
if err != nil {
c.log.With("object_id", e.id).Warnf("GC: object close error: %v", err)
}
if !closed {
e.setActive(true)
continue
} else {
closedNum++
c.mu.Lock()
e.setClosed()
delete(c.data, e.id)
c.mu.Unlock()
} }
} }
c.log.Infof("GC: removed %d; cache size: %d", len(toClose), size) c.metricsClosed(closedNum, size)
if len(toClose) > 0 && c.metrics != nil {
c.metrics.gc.Add(float64(len(toClose)))
}
c.mu.Lock()
for _, e := range toClose {
close(e.close)
delete(c.data, e.id)
}
c.mu.Unlock()
} }
func (c *oCache) Len() int { func (c *oCache) Len() int {
@ -418,25 +313,34 @@ func (c *oCache) Close() (err error) {
} }
c.closed = true c.closed = true
close(c.closeCh) close(c.closeCh)
var toClose, alreadyClosing []*entry var toClose []*entry
for _, e := range c.data { for _, e := range c.data {
if e.isClosing { toClose = append(toClose, e)
alreadyClosing = append(alreadyClosing, e)
} else {
toClose = append(toClose, e)
}
} }
c.mu.Unlock() c.mu.Unlock()
for _, e := range toClose { for _, e := range toClose {
<-e.load if _, err := c.remove(context.Background(), e); err != nil && err != ErrNotExists {
if e.value != nil { c.log.With("object_id", e.id).Warnf("cache close: object close error: %v", err)
if clErr := e.value.Close(); clErr != nil {
c.log.With("object_id", e.id).Warnf("cache close: object close error: %v", clErr)
}
} }
} }
for _, e := range alreadyClosing {
<-e.close
}
return nil return nil
} }
func (c *oCache) metricsGet(hit bool) {
if c.metrics == nil {
return
}
if hit {
c.metrics.hit.Inc()
} else {
c.metrics.miss.Inc()
}
}
func (c *oCache) metricsClosed(closedLen, size int) {
c.log.Infof("GC: removed %d; cache size: %d", closedLen, size)
if c.metrics == nil || closedLen == 0 {
return
}
c.metrics.gc.Add(float64(closedLen))
}

View File

@ -3,6 +3,8 @@ package ocache
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"sync"
"sync/atomic" "sync/atomic"
"testing" "testing"
"time" "time"
@ -11,26 +13,48 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var ctx = context.Background()
type testObject struct { type testObject struct {
name string name string
closeErr error closeErr error
closeCh chan struct{} closeCh chan struct{}
tryReturn bool
closeCalled bool
tryCloseCalled bool
} }
func NewTestObject(name string, closeCh chan struct{}) *testObject { func NewTestObject(name string, tryReturn bool, closeCh chan struct{}) *testObject {
return &testObject{ return &testObject{
name: name, name: name,
closeCh: closeCh, closeCh: closeCh,
tryReturn: tryReturn,
} }
} }
func (t *testObject) Close() (err error) { func (t *testObject) Close() (err error) {
if t.closeCalled || (t.tryCloseCalled && t.tryReturn) {
panic("close called twice")
}
t.closeCalled = true
if t.closeCh != nil { if t.closeCh != nil {
<-t.closeCh <-t.closeCh
} }
return t.closeErr return t.closeErr
} }
func (t *testObject) TryClose(objectTTL time.Duration) (res bool, err error) {
if t.closeCalled || (t.tryCloseCalled && t.tryReturn) {
panic("close called twice")
}
t.tryCloseCalled = true
if t.closeCh != nil {
<-t.closeCh
return t.tryReturn, t.closeErr
}
return t.tryReturn, nil
}
func TestOCache_Get(t *testing.T) { func TestOCache_Get(t *testing.T) {
t.Run("successful", func(t *testing.T) { t.Run("successful", func(t *testing.T) {
c := New(func(ctx context.Context, id string) (value Object, err error) { c := New(func(ctx context.Context, id string) (value Object, err error) {
@ -116,42 +140,37 @@ func TestOCache_Get(t *testing.T) {
} }
func TestOCache_GC(t *testing.T) { func TestOCache_GC(t *testing.T) {
t.Run("test without close wait", func(t *testing.T) { t.Run("test gc expired object", func(t *testing.T) {
c := New(func(ctx context.Context, id string) (value Object, err error) { c := New(func(ctx context.Context, id string) (value Object, err error) {
return &testObject{name: id}, nil return NewTestObject(id, true, nil), nil
}, WithTTL(time.Millisecond*10), WithRefCounter(true)) }, WithTTL(time.Millisecond*10))
val, err := c.Get(context.TODO(), "id") val, err := c.Get(context.TODO(), "id")
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, val) require.NotNil(t, val)
assert.Equal(t, 1, c.Len()) assert.Equal(t, 1, c.Len())
c.GC() c.GC()
assert.Equal(t, 1, c.Len()) assert.Equal(t, 1, c.Len())
time.Sleep(time.Millisecond * 30) time.Sleep(time.Millisecond * 20)
c.GC()
assert.Equal(t, 1, c.Len())
assert.True(t, c.Release("id"))
c.GC() c.GC()
assert.Equal(t, 0, c.Len()) assert.Equal(t, 0, c.Len())
assert.False(t, c.Release("id"))
}) })
t.Run("test with close wait", func(t *testing.T) { t.Run("test gc tryClose true, close before get", func(t *testing.T) {
closeCh := make(chan struct{}) closeCh := make(chan struct{})
getCh := make(chan struct{}) getCh := make(chan struct{})
c := New(func(ctx context.Context, id string) (value Object, err error) { c := New(func(ctx context.Context, id string) (value Object, err error) {
return NewTestObject(id, closeCh), nil return NewTestObject(id, true, closeCh), nil
}, WithTTL(time.Millisecond*10), WithRefCounter(true)) }, WithTTL(time.Millisecond*10))
val, err := c.Get(context.TODO(), "id") val, err := c.Get(context.TODO(), "id")
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, val) require.NotNil(t, val)
assert.Equal(t, 1, c.Len()) assert.Equal(t, 1, c.Len())
assert.True(t, c.Release("id"))
// making ttl pass // making ttl pass
time.Sleep(time.Millisecond * 40) time.Sleep(time.Millisecond * 20)
// first gc will be run after 20 secs, so calling it manually // first gc will be run after 20 secs, so calling it manually
go c.GC() go c.GC()
// waiting until all objects are marked as closing // waiting until all objects are marked as closing
time.Sleep(time.Millisecond * 40) time.Sleep(time.Millisecond * 20)
var events []string var events []string
go func() { go func() {
_, err := c.Get(context.TODO(), "id") _, err := c.Get(context.TODO(), "id")
@ -160,47 +179,313 @@ func TestOCache_GC(t *testing.T) {
events = append(events, "get") events = append(events, "get")
close(getCh) close(getCh)
}() }()
events = append(events, "close")
// sleeping to make sure that Get is called // sleeping to make sure that Get is called
time.Sleep(time.Millisecond * 40) time.Sleep(time.Millisecond * 20)
events = append(events, "close")
close(closeCh) close(closeCh)
<-getCh <-getCh
require.Equal(t, []string{"close", "get"}, events) require.Equal(t, []string{"close", "get"}, events)
}) })
t.Run("test gc tryClose false, many parallel get", func(t *testing.T) {
timesCalled := &atomic.Int32{}
obj := NewTestObject("id", false, nil)
c := New(func(ctx context.Context, id string) (value Object, err error) {
timesCalled.Add(1)
return obj, nil
}, WithTTL(0))
val, err := c.Get(context.TODO(), "id")
require.NoError(t, err)
require.NotNil(t, val)
assert.Equal(t, 1, c.Len())
begin := make(chan struct{})
wg := sync.WaitGroup{}
once := sync.Once{}
wg.Add(1)
go func() {
<-begin
c.GC()
wg.Done()
}()
for i := 0; i < 50; i++ {
wg.Add(1)
go func(i int) {
once.Do(func() {
close(begin)
})
if i%2 != 0 {
time.Sleep(time.Millisecond)
}
_, err := c.Get(context.TODO(), "id")
require.NoError(t, err)
wg.Done()
}(i)
}
require.NoError(t, err)
wg.Wait()
require.Equal(t, timesCalled.Load(), int32(1))
require.True(t, obj.tryCloseCalled)
})
t.Run("test gc tryClose different, many objects", func(t *testing.T) {
tryCloseIds := make(map[string]bool)
called := make(map[string]int)
max := 1000
getId := func(i int) string {
return fmt.Sprintf("id%d", i)
}
for i := 0; i < max; i++ {
if i%2 == 1 {
tryCloseIds[getId(i)] = true
} else {
tryCloseIds[getId(i)] = false
}
}
c := New(func(ctx context.Context, id string) (value Object, err error) {
called[id] = called[id] + 1
return NewTestObject(id, tryCloseIds[id], nil), nil
}, WithTTL(time.Millisecond*10))
for i := 0; i < max; i++ {
val, err := c.Get(context.TODO(), getId(i))
require.NoError(t, err)
require.NotNil(t, val)
}
assert.Equal(t, max, c.Len())
time.Sleep(time.Millisecond * 20)
c.GC()
for i := 0; i < max; i++ {
val, err := c.Get(context.TODO(), getId(i))
require.NoError(t, err)
require.NotNil(t, val)
}
for i := 0; i < max; i++ {
val, err := c.Get(context.TODO(), getId(i))
require.NoError(t, err)
require.NotNil(t, val)
require.Equal(t, called[getId(i)], i%2+1)
}
})
} }
func Test_OCache_Remove(t *testing.T) { func Test_OCache_Remove(t *testing.T) {
closeCh := make(chan struct{}) t.Run("remove simple", func(t *testing.T) {
getCh := make(chan struct{}) closeCh := make(chan struct{})
getCh := make(chan struct{})
c := New(func(ctx context.Context, id string) (value Object, err error) {
return NewTestObject(id, false, closeCh), nil
}, WithTTL(time.Millisecond*10))
c := New(func(ctx context.Context, id string) (value Object, err error) { val, err := c.Get(context.TODO(), "id")
return NewTestObject(id, closeCh), nil
}, WithTTL(time.Millisecond*10))
val, err := c.Get(context.TODO(), "id")
require.NoError(t, err)
require.NotNil(t, val)
assert.Equal(t, 1, c.Len())
// removing the object, so we will wait on closing
go func() {
_, err := c.Remove("id")
require.NoError(t, err)
}()
time.Sleep(time.Millisecond * 40)
var events []string
go func() {
_, err := c.Get(context.TODO(), "id")
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, val) require.NotNil(t, val)
events = append(events, "get") assert.Equal(t, 1, c.Len())
close(getCh) // removing the object, so we will wait on closing
}() go func() {
events = append(events, "close") _, err := c.Remove(ctx, "id")
// sleeping to make sure that Get is called require.NoError(t, err)
time.Sleep(time.Millisecond * 40) }()
close(closeCh) time.Sleep(time.Millisecond * 20)
<-getCh var events []string
require.Equal(t, []string{"close", "get"}, events) go func() {
_, err := c.Get(context.TODO(), "id")
require.NoError(t, err)
require.NotNil(t, val)
events = append(events, "get")
close(getCh)
}()
// sleeping to make sure that Get is called
time.Sleep(time.Millisecond * 20)
events = append(events, "close")
close(closeCh)
<-getCh
require.Equal(t, []string{"close", "get"}, events)
})
t.Run("test remove while gc, tryClose false", func(t *testing.T) {
closeCh := make(chan struct{})
removeCh := make(chan struct{})
c := New(func(ctx context.Context, id string) (value Object, err error) {
return NewTestObject(id, false, closeCh), nil
}, WithTTL(time.Millisecond*10))
val, err := c.Get(context.TODO(), "id")
require.NoError(t, err)
require.NotNil(t, val)
assert.Equal(t, 1, c.Len())
time.Sleep(time.Millisecond * 20)
go c.GC()
time.Sleep(time.Millisecond * 20)
var events []string
go func() {
ok, err := c.Remove(ctx, "id")
require.NoError(t, err)
require.True(t, ok)
events = append(events, "remove")
close(removeCh)
}()
time.Sleep(time.Millisecond * 20)
events = append(events, "close")
close(closeCh)
<-removeCh
require.Equal(t, []string{"close", "remove"}, events)
})
t.Run("test remove while gc, tryClose true", func(t *testing.T) {
closeCh := make(chan struct{})
removeCh := make(chan struct{})
c := New(func(ctx context.Context, id string) (value Object, err error) {
return NewTestObject(id, true, closeCh), nil
}, WithTTL(time.Millisecond*10))
val, err := c.Get(context.TODO(), "id")
require.NoError(t, err)
require.NotNil(t, val)
assert.Equal(t, 1, c.Len())
time.Sleep(time.Millisecond * 20)
go c.GC()
time.Sleep(time.Millisecond * 20)
var events []string
go func() {
ok, err := c.Remove(ctx, "id")
require.NoError(t, err)
require.False(t, ok)
events = append(events, "remove")
close(removeCh)
}()
time.Sleep(time.Millisecond * 20)
events = append(events, "close")
close(closeCh)
<-removeCh
require.Equal(t, []string{"close", "remove"}, events)
})
t.Run("test gc while remove, tryClose true", func(t *testing.T) {
closeCh := make(chan struct{})
removeCh := make(chan struct{})
c := New(func(ctx context.Context, id string) (value Object, err error) {
return NewTestObject(id, true, closeCh), nil
}, WithTTL(time.Millisecond*10))
val, err := c.Get(context.TODO(), "id")
require.NoError(t, err)
require.NotNil(t, val)
assert.Equal(t, 1, c.Len())
go func() {
ok, err := c.Remove(ctx, "id")
require.NoError(t, err)
require.True(t, ok)
close(removeCh)
}()
time.Sleep(20 * time.Millisecond)
c.GC()
close(closeCh)
<-removeCh
})
}
func TestOCacheFuzzy(t *testing.T) {
t.Run("test many objects gc, get and remove simultaneously, close after", func(t *testing.T) {
tryCloseIds := make(map[string]bool)
max := 2000
getId := func(i int) string {
return fmt.Sprintf("id%d", i)
}
for i := 0; i < max; i++ {
if i%2 == 1 {
tryCloseIds[getId(i)] = true
} else {
tryCloseIds[getId(i)] = false
}
}
c := New(func(ctx context.Context, id string) (value Object, err error) {
return NewTestObject(id, tryCloseIds[id], nil), nil
}, WithTTL(time.Nanosecond))
stopGC := make(chan struct{})
wg := sync.WaitGroup{}
go func() {
for {
select {
case <-stopGC:
return
default:
c.GC()
}
}
}()
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 10; j++ {
for i := 0; i < max; i++ {
val, err := c.Get(context.TODO(), getId(i))
require.NoError(t, err)
require.NotNil(t, val)
}
}
}()
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 10; j++ {
for i := 0; i < max; i++ {
c.Remove(ctx, getId(i))
}
}
}()
wg.Wait()
close(stopGC)
err := c.Close()
require.NoError(t, err)
require.Equal(t, 0, c.Len())
})
t.Run("test many objects gc, get, remove and close simultaneously", func(t *testing.T) {
tryCloseIds := make(map[string]bool)
max := 2000
getId := func(i int) string {
return fmt.Sprintf("id%d", i)
}
for i := 0; i < max; i++ {
if i%2 == 1 {
tryCloseIds[getId(i)] = true
} else {
tryCloseIds[getId(i)] = false
}
}
c := New(func(ctx context.Context, id string) (value Object, err error) {
return NewTestObject(id, tryCloseIds[id], nil), nil
}, WithTTL(time.Nanosecond))
go func() {
for {
c.GC()
}
}()
go func() {
for j := 0; j < 10; j++ {
for i := 0; i < max; i++ {
val, err := c.Get(context.TODO(), getId(i))
if err == ErrClosed {
return
}
require.NoError(t, err)
require.NotNil(t, val)
}
}
}()
go func() {
for j := 0; j < 10; j++ {
for i := 0; i < max; i++ {
c.Remove(ctx, getId(i))
}
}
}()
time.Sleep(time.Millisecond)
err := c.Close()
require.NoError(t, err)
require.Equal(t, 0, c.Len())
})
} }

View File

@ -51,6 +51,10 @@ func (p pushSpaceRequestMatcher) String() string {
type mockPeer struct{} type mockPeer struct{}
func (m mockPeer) TryClose(objectTTL time.Duration) (res bool, err error) {
return true, m.Close()
}
func (m mockPeer) Id() string { func (m mockPeer) Id() string {
return "mockId" return "mockId"
} }

View File

@ -88,7 +88,7 @@ func (a *aclRecordBuilder) BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyByt
Identity: state.Identity(), Identity: state.Identity(),
Data: marshalledJoin, Data: marshalledJoin,
CurrentReadKeyHash: state.CurrentReadKeyHash(), CurrentReadKeyHash: state.CurrentReadKeyHash(),
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().Unix(),
} }
marshalledRecord, err := aclRecord.Marshal() marshalledRecord, err := aclRecord.Marshal()
if err != nil { if err != nil {

View File

@ -126,7 +126,7 @@ func (t *AclListStorageBuilder) parseRecord(rec *Record, prevId string) *aclreco
Identity: []byte(t.keychain.GetIdentity(rec.Identity)), Identity: []byte(t.keychain.GetIdentity(rec.Identity)),
Data: bytes, Data: bytes,
CurrentReadKeyHash: k.Hash, CurrentReadKeyHash: k.Hash,
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().Unix(),
} }
} }

View File

@ -3,6 +3,7 @@ package objecttree
import ( import (
"errors" "errors"
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
"github.com/gogo/protobuf/proto"
) )
var ( var (
@ -48,6 +49,11 @@ func NewChange(id string, ch *treechangeproto.TreeChange, signature []byte) *Cha
} }
func NewChangeFromRoot(id string, ch *treechangeproto.RootChange, signature []byte) *Change { func NewChangeFromRoot(id string, ch *treechangeproto.RootChange, signature []byte) *Change {
changeInfo := &treechangeproto.TreeChangeInfo{
ChangeType: ch.ChangeType,
ChangePayload: ch.ChangePayload,
}
data, _ := proto.Marshal(changeInfo)
return &Change{ return &Change{
Next: nil, Next: nil,
AclHeadId: ch.AclHeadId, AclHeadId: ch.AclHeadId,
@ -56,7 +62,8 @@ func NewChangeFromRoot(id string, ch *treechangeproto.RootChange, signature []by
Timestamp: ch.Timestamp, Timestamp: ch.Timestamp,
Identity: string(ch.Identity), Identity: string(ch.Identity),
Signature: signature, Signature: signature,
Data: []byte(ch.ChangeType), Data: data,
Model: changeInfo,
} }
} }

View File

@ -26,13 +26,14 @@ type BuilderContent struct {
} }
type InitialContent struct { type InitialContent struct {
AclHeadId string AclHeadId string
Identity []byte Identity []byte
SigningKey signingkey.PrivKey SigningKey signingkey.PrivKey
SpaceId string SpaceId string
Seed []byte Seed []byte
ChangeType string ChangeType string
Timestamp int64 ChangePayload []byte
Timestamp int64
} }
type nonVerifiableChangeBuilder struct { type nonVerifiableChangeBuilder struct {
@ -122,41 +123,35 @@ func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeCha
func (c *changeBuilder) BuildRoot(payload InitialContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) { func (c *changeBuilder) BuildRoot(payload InitialContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) {
change := &treechangeproto.RootChange{ change := &treechangeproto.RootChange{
AclHeadId: payload.AclHeadId, AclHeadId: payload.AclHeadId,
Timestamp: payload.Timestamp, Timestamp: payload.Timestamp,
Identity: payload.Identity, Identity: payload.Identity,
ChangeType: payload.ChangeType, ChangeType: payload.ChangeType,
SpaceId: payload.SpaceId, ChangePayload: payload.ChangePayload,
Seed: payload.Seed, SpaceId: payload.SpaceId,
Seed: payload.Seed,
} }
marshalledChange, err := proto.Marshal(change) marshalledChange, err := proto.Marshal(change)
if err != nil { if err != nil {
return return
} }
signature, err := payload.SigningKey.Sign(marshalledChange) signature, err := payload.SigningKey.Sign(marshalledChange)
if err != nil { if err != nil {
return return
} }
raw := &treechangeproto.RawTreeChange{ raw := &treechangeproto.RawTreeChange{
Payload: marshalledChange, Payload: marshalledChange,
Signature: signature, Signature: signature,
} }
marshalledRawChange, err := proto.Marshal(raw) marshalledRawChange, err := proto.Marshal(raw)
if err != nil { if err != nil {
return return
} }
id, err := cidutil.NewCidFromBytes(marshalledRawChange) id, err := cidutil.NewCidFromBytes(marshalledRawChange)
if err != nil { if err != nil {
return return
} }
ch = NewChangeFromRoot(id, change, signature) ch = NewChangeFromRoot(id, change, signature)
rawIdChange = &treechangeproto.RawTreeChangeWithId{ rawIdChange = &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange, RawChange: marshalledRawChange,
Id: id, Id: id,
@ -170,7 +165,7 @@ func (c *changeBuilder) Build(payload BuilderContent) (ch *Change, rawIdChange *
AclHeadId: payload.AclHeadId, AclHeadId: payload.AclHeadId,
SnapshotBaseId: payload.SnapshotBaseId, SnapshotBaseId: payload.SnapshotBaseId,
CurrentReadKeyHash: payload.CurrentReadKeyHash, CurrentReadKeyHash: payload.CurrentReadKeyHash,
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().Unix(),
Identity: payload.Identity, Identity: payload.Identity,
IsSnapshot: payload.IsSnapshot, IsSnapshot: payload.IsSnapshot,
} }
@ -184,34 +179,27 @@ func (c *changeBuilder) Build(payload BuilderContent) (ch *Change, rawIdChange *
} else { } else {
change.ChangesData = payload.Content change.ChangesData = payload.Content
} }
marshalledChange, err := proto.Marshal(change) marshalledChange, err := proto.Marshal(change)
if err != nil { if err != nil {
return return
} }
signature, err := payload.SigningKey.Sign(marshalledChange) signature, err := payload.SigningKey.Sign(marshalledChange)
if err != nil { if err != nil {
return return
} }
raw := &treechangeproto.RawTreeChange{ raw := &treechangeproto.RawTreeChange{
Payload: marshalledChange, Payload: marshalledChange,
Signature: signature, Signature: signature,
} }
marshalledRawChange, err := proto.Marshal(raw) marshalledRawChange, err := proto.Marshal(raw)
if err != nil { if err != nil {
return return
} }
id, err := cidutil.NewCidFromBytes(marshalledRawChange) id, err := cidutil.NewCidFromBytes(marshalledRawChange)
if err != nil { if err != nil {
return return
} }
ch = NewChange(id, change, signature) ch = NewChange(id, change, signature)
rawIdChange = &treechangeproto.RawTreeChangeWithId{ rawIdChange = &treechangeproto.RawTreeChangeWithId{
RawChange: marshalledRawChange, RawChange: marshalledRawChange,
Id: id, Id: id,
@ -264,7 +252,6 @@ func (c *changeBuilder) unmarshallRawChange(raw *treechangeproto.RawTreeChange,
ch = NewChangeFromRoot(id, unmarshalled, raw.Signature) ch = NewChangeFromRoot(id, unmarshalled, raw.Signature)
return return
} }
unmarshalled := &treechangeproto.TreeChange{} unmarshalled := &treechangeproto.TreeChange{}
err = proto.Unmarshal(raw.Payload, unmarshalled) err = proto.Unmarshal(raw.Payload, unmarshalled)
if err != nil { if err != nil {

View File

@ -7,6 +7,7 @@ package mock_objecttree
import ( import (
context "context" context "context"
reflect "reflect" reflect "reflect"
time "time"
list "github.com/anytypeio/any-sync/commonspace/object/acl/list" list "github.com/anytypeio/any-sync/commonspace/object/acl/list"
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
@ -82,6 +83,20 @@ func (mr *MockObjectTreeMockRecorder) AddRawChanges(arg0, arg1 interface{}) *gom
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawChanges", reflect.TypeOf((*MockObjectTree)(nil).AddRawChanges), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawChanges", reflect.TypeOf((*MockObjectTree)(nil).AddRawChanges), arg0, arg1)
} }
// ChangeInfo mocks base method.
func (m *MockObjectTree) ChangeInfo() *treechangeproto.TreeChangeInfo {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChangeInfo")
ret0, _ := ret[0].(*treechangeproto.TreeChangeInfo)
return ret0
}
// ChangeInfo indicates an expected call of ChangeInfo.
func (mr *MockObjectTreeMockRecorder) ChangeInfo() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeInfo", reflect.TypeOf((*MockObjectTree)(nil).ChangeInfo))
}
// ChangesAfterCommonSnapshot mocks base method. // ChangesAfterCommonSnapshot mocks base method.
func (m *MockObjectTree) ChangesAfterCommonSnapshot(arg0, arg1 []string) ([]*treechangeproto.RawTreeChangeWithId, error) { func (m *MockObjectTree) ChangesAfterCommonSnapshot(arg0, arg1 []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -336,6 +351,21 @@ func (mr *MockObjectTreeMockRecorder) Storage() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Storage", reflect.TypeOf((*MockObjectTree)(nil).Storage)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Storage", reflect.TypeOf((*MockObjectTree)(nil).Storage))
} }
// TryClose mocks base method.
func (m *MockObjectTree) TryClose(arg0 time.Duration) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TryClose", arg0)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// TryClose indicates an expected call of TryClose.
func (mr *MockObjectTreeMockRecorder) TryClose(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryClose", reflect.TypeOf((*MockObjectTree)(nil).TryClose), arg0)
}
// TryLock mocks base method. // TryLock mocks base method.
func (m *MockObjectTree) TryLock() bool { func (m *MockObjectTree) TryLock() bool {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@ -5,6 +5,7 @@ import (
"context" "context"
"errors" "errors"
"sync" "sync"
"time"
"github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto"
"github.com/anytypeio/any-sync/commonspace/object/acl/list" "github.com/anytypeio/any-sync/commonspace/object/acl/list"
@ -52,6 +53,7 @@ type ReadableObjectTree interface {
Id() string Id() string
Header() *treechangeproto.RawTreeChangeWithId Header() *treechangeproto.RawTreeChangeWithId
UnmarshalledHeader() *Change UnmarshalledHeader() *Change
ChangeInfo() *treechangeproto.TreeChangeInfo
Heads() []string Heads() []string
Root() *Change Root() *Change
@ -81,6 +83,7 @@ type ObjectTree interface {
Delete() error Delete() error
Close() error Close() error
TryClose(objectTTL time.Duration) (bool, error)
} }
type objectTree struct { type objectTree struct {
@ -142,6 +145,10 @@ func (ot *objectTree) UnmarshalledHeader() *Change {
return ot.root return ot.root
} }
func (ot *objectTree) ChangeInfo() *treechangeproto.TreeChangeInfo {
return ot.root.Model.(*treechangeproto.TreeChangeInfo)
}
func (ot *objectTree) Storage() treestorage.TreeStorage { func (ot *objectTree) Storage() treestorage.TreeStorage {
return ot.treeStorage return ot.treeStorage
} }
@ -555,6 +562,10 @@ func (ot *objectTree) Root() *Change {
return ot.tree.Root() return ot.tree.Root()
} }
func (ot *objectTree) TryClose(objectTTL time.Duration) (bool, error) {
return true, ot.Close()
}
func (ot *objectTree) Close() error { func (ot *objectTree) Close() error {
return nil return nil
} }

View File

@ -12,11 +12,12 @@ import (
) )
type ObjectTreeCreatePayload struct { type ObjectTreeCreatePayload struct {
SignKey signingkey.PrivKey SignKey signingkey.PrivKey
ChangeType string ChangeType string
SpaceId string ChangePayload []byte
Identity []byte SpaceId string
IsEncrypted bool Identity []byte
IsEncrypted bool
} }
type HistoryTreeParams struct { type HistoryTreeParams struct {
@ -75,7 +76,7 @@ func CreateObjectTreeRoot(payload ObjectTreeCreatePayload, aclList list.AclList)
if err != nil { if err != nil {
return return
} }
return createObjectTreeRoot(payload, time.Now().UnixNano(), bytes, aclList) return createObjectTreeRoot(payload, time.Now().Unix(), bytes, aclList)
} }
func DeriveObjectTreeRoot(payload ObjectTreeCreatePayload, aclList list.AclList) (root *treechangeproto.RawTreeChangeWithId, err error) { func DeriveObjectTreeRoot(payload ObjectTreeCreatePayload, aclList list.AclList) (root *treechangeproto.RawTreeChangeWithId, err error) {
@ -125,7 +126,7 @@ func CreateObjectTree(
if err != nil { if err != nil {
return return
} }
return createObjectTree(payload, time.Now().UnixNano(), bytes, aclList, createStorage) return createObjectTree(payload, time.Now().Unix(), bytes, aclList, createStorage)
} }
func createObjectTree( func createObjectTree(
@ -165,13 +166,14 @@ func createObjectTreeRoot(
return return
} }
cnt := InitialContent{ cnt := InitialContent{
AclHeadId: aclHeadId, AclHeadId: aclHeadId,
Identity: payload.Identity, Identity: payload.Identity,
SigningKey: payload.SignKey, SigningKey: payload.SignKey,
SpaceId: payload.SpaceId, SpaceId: payload.SpaceId,
ChangeType: payload.ChangeType, ChangeType: payload.ChangeType,
Timestamp: timestamp, ChangePayload: payload.ChangePayload,
Seed: seed, Timestamp: timestamp,
Seed: seed,
} }
_, root, err = NewChangeBuilder(keychain.NewKeychain(), nil).BuildRoot(cnt) _, root, err = NewChangeBuilder(keychain.NewKeychain(), nil).BuildRoot(cnt)

View File

@ -125,7 +125,7 @@ func TestTree_Hash(t *testing.T) {
} }
func TestTree_AddFuzzy(t *testing.T) { func TestTree_AddFuzzy(t *testing.T) {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().Unix())
getChanges := func() []*Change { getChanges := func() []*Change {
changes := []*Change{ changes := []*Change{
newChange("1", "root", "root"), newChange("1", "root", "root"),

View File

@ -7,6 +7,7 @@ package mock_synctree
import ( import (
context "context" context "context"
reflect "reflect" reflect "reflect"
time "time"
list "github.com/anytypeio/any-sync/commonspace/object/acl/list" list "github.com/anytypeio/any-sync/commonspace/object/acl/list"
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
@ -193,6 +194,20 @@ func (mr *MockSyncTreeMockRecorder) AddRawChanges(arg0, arg1 interface{}) *gomoc
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawChanges", reflect.TypeOf((*MockSyncTree)(nil).AddRawChanges), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawChanges", reflect.TypeOf((*MockSyncTree)(nil).AddRawChanges), arg0, arg1)
} }
// ChangeInfo mocks base method.
func (m *MockSyncTree) ChangeInfo() *treechangeproto.TreeChangeInfo {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChangeInfo")
ret0, _ := ret[0].(*treechangeproto.TreeChangeInfo)
return ret0
}
// ChangeInfo indicates an expected call of ChangeInfo.
func (mr *MockSyncTreeMockRecorder) ChangeInfo() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeInfo", reflect.TypeOf((*MockSyncTree)(nil).ChangeInfo))
}
// ChangesAfterCommonSnapshot mocks base method. // ChangesAfterCommonSnapshot mocks base method.
func (m *MockSyncTree) ChangesAfterCommonSnapshot(arg0, arg1 []string) ([]*treechangeproto.RawTreeChangeWithId, error) { func (m *MockSyncTree) ChangesAfterCommonSnapshot(arg0, arg1 []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -487,6 +502,21 @@ func (mr *MockSyncTreeMockRecorder) SyncWithPeer(arg0, arg1 interface{}) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncWithPeer", reflect.TypeOf((*MockSyncTree)(nil).SyncWithPeer), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncWithPeer", reflect.TypeOf((*MockSyncTree)(nil).SyncWithPeer), arg0, arg1)
} }
// TryClose mocks base method.
func (m *MockSyncTree) TryClose(arg0 time.Duration) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TryClose", arg0)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// TryClose indicates an expected call of TryClose.
func (mr *MockSyncTreeMockRecorder) TryClose(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryClose", reflect.TypeOf((*MockSyncTree)(nil).TryClose), arg0)
}
// TryLock mocks base method. // TryLock mocks base method.
func (m *MockSyncTree) TryLock() bool { func (m *MockSyncTree) TryLock() bool {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@ -3,6 +3,7 @@ package synctree
import ( import (
"context" "context"
"errors" "errors"
"time"
"github.com/anytypeio/any-sync/app/logger" "github.com/anytypeio/any-sync/app/logger"
"github.com/anytypeio/any-sync/commonspace/object/acl/list" "github.com/anytypeio/any-sync/commonspace/object/acl/list"
@ -209,6 +210,10 @@ func (s *syncTree) Delete() (err error) {
return return
} }
func (s *syncTree) TryClose(objectTTL time.Duration) (bool, error) {
return true, s.Close()
}
func (s *syncTree) Close() (err error) { func (s *syncTree) Close() (err error) {
log.Debug("closing sync tree", zap.String("id", s.Id())) log.Debug("closing sync tree", zap.String("id", s.Id()))
defer func() { defer func() {

View File

@ -16,6 +16,8 @@ message RootChange {
bytes seed = 5; bytes seed = 5;
// Identity is a public key of the tree's creator // Identity is a public key of the tree's creator
bytes identity = 6; bytes identity = 6;
// ChangePayload is a payload related to ChangeType
bytes changePayload = 7;
} }
// TreeChange is a change of a tree // TreeChange is a change of a tree
@ -94,3 +96,9 @@ message TreeFullSyncResponse {
message TreeErrorResponse { message TreeErrorResponse {
string error = 1; string error = 1;
} }
// TreeChangeInfo is used internally in Tree implementation for ease of marshalling
message TreeChangeInfo {
string changeType = 1;
bytes changePayload = 2;
}

View File

@ -36,6 +36,8 @@ type RootChange struct {
Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"` Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"`
// Identity is a public key of the tree's creator // Identity is a public key of the tree's creator
Identity []byte `protobuf:"bytes,6,opt,name=identity,proto3" json:"identity,omitempty"` Identity []byte `protobuf:"bytes,6,opt,name=identity,proto3" json:"identity,omitempty"`
// ChangePayload is a payload related to ChangeType
ChangePayload []byte `protobuf:"bytes,7,opt,name=changePayload,proto3" json:"changePayload,omitempty"`
} }
func (m *RootChange) Reset() { *m = RootChange{} } func (m *RootChange) Reset() { *m = RootChange{} }
@ -113,6 +115,13 @@ func (m *RootChange) GetIdentity() []byte {
return nil return nil
} }
func (m *RootChange) GetChangePayload() []byte {
if m != nil {
return m.ChangePayload
}
return nil
}
// TreeChange is a change of a tree // TreeChange is a change of a tree
type TreeChange struct { type TreeChange struct {
// TreeHeadIds are previous ids for this TreeChange // TreeHeadIds are previous ids for this TreeChange
@ -725,6 +734,59 @@ func (m *TreeErrorResponse) GetError() string {
return "" return ""
} }
// TreeChangeInfo is used internally in Tree implementation for ease of marshalling
type TreeChangeInfo struct {
ChangeType string `protobuf:"bytes,1,opt,name=changeType,proto3" json:"changeType,omitempty"`
ChangePayload []byte `protobuf:"bytes,2,opt,name=changePayload,proto3" json:"changePayload,omitempty"`
}
func (m *TreeChangeInfo) Reset() { *m = TreeChangeInfo{} }
func (m *TreeChangeInfo) String() string { return proto.CompactTextString(m) }
func (*TreeChangeInfo) ProtoMessage() {}
func (*TreeChangeInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_5033f0301ef9b772, []int{10}
}
func (m *TreeChangeInfo) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *TreeChangeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_TreeChangeInfo.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *TreeChangeInfo) XXX_Merge(src proto.Message) {
xxx_messageInfo_TreeChangeInfo.Merge(m, src)
}
func (m *TreeChangeInfo) XXX_Size() int {
return m.Size()
}
func (m *TreeChangeInfo) XXX_DiscardUnknown() {
xxx_messageInfo_TreeChangeInfo.DiscardUnknown(m)
}
var xxx_messageInfo_TreeChangeInfo proto.InternalMessageInfo
func (m *TreeChangeInfo) GetChangeType() string {
if m != nil {
return m.ChangeType
}
return ""
}
func (m *TreeChangeInfo) GetChangePayload() []byte {
if m != nil {
return m.ChangePayload
}
return nil
}
func init() { func init() {
proto.RegisterType((*RootChange)(nil), "treechange.RootChange") proto.RegisterType((*RootChange)(nil), "treechange.RootChange")
proto.RegisterType((*TreeChange)(nil), "treechange.TreeChange") proto.RegisterType((*TreeChange)(nil), "treechange.TreeChange")
@ -736,6 +798,7 @@ func init() {
proto.RegisterType((*TreeFullSyncRequest)(nil), "treechange.TreeFullSyncRequest") proto.RegisterType((*TreeFullSyncRequest)(nil), "treechange.TreeFullSyncRequest")
proto.RegisterType((*TreeFullSyncResponse)(nil), "treechange.TreeFullSyncResponse") proto.RegisterType((*TreeFullSyncResponse)(nil), "treechange.TreeFullSyncResponse")
proto.RegisterType((*TreeErrorResponse)(nil), "treechange.TreeErrorResponse") proto.RegisterType((*TreeErrorResponse)(nil), "treechange.TreeErrorResponse")
proto.RegisterType((*TreeChangeInfo)(nil), "treechange.TreeChangeInfo")
} }
func init() { func init() {
@ -743,48 +806,51 @@ func init() {
} }
var fileDescriptor_5033f0301ef9b772 = []byte{ var fileDescriptor_5033f0301ef9b772 = []byte{
// 656 bytes of a gzipped FileDescriptorProto // 690 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xc1, 0x6e, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xc1, 0x4e, 0xdb, 0x4a,
0x10, 0xf5, 0x3a, 0x69, 0xd3, 0x4e, 0xd3, 0x16, 0xb6, 0x3d, 0x58, 0x15, 0x18, 0xcb, 0x07, 0x08, 0x14, 0xf5, 0x38, 0x01, 0xc3, 0x25, 0xc0, 0x7b, 0x03, 0x0b, 0x0b, 0xbd, 0xe7, 0x5a, 0x56, 0xd5,
0x97, 0x56, 0x2a, 0x27, 0x10, 0x52, 0x45, 0x4b, 0x8b, 0xab, 0x0a, 0x84, 0xb6, 0x05, 0x24, 0x6e, 0xa6, 0x1b, 0x90, 0xe8, 0xaa, 0x55, 0x25, 0x54, 0x28, 0xd4, 0x11, 0x6a, 0x85, 0x06, 0x4a, 0xa5,
0x5b, 0x7b, 0x68, 0x8c, 0x12, 0xdb, 0x78, 0x37, 0x54, 0xf9, 0x00, 0x2e, 0x20, 0x21, 0x3e, 0x81, 0xee, 0x06, 0xfb, 0x42, 0x5c, 0x25, 0xb6, 0xeb, 0x99, 0x14, 0xe5, 0x03, 0xba, 0x69, 0xa5, 0xaa,
0x6f, 0xe0, 0x0f, 0xb8, 0x71, 0xec, 0x91, 0x23, 0x6a, 0x7e, 0x04, 0xed, 0x3a, 0x4e, 0xd6, 0x6e, 0x9f, 0xd0, 0x5f, 0xe9, 0xae, 0x4b, 0x96, 0x2c, 0x2b, 0xf8, 0x91, 0xca, 0x63, 0x3b, 0xb1, 0x1d,
0x0e, 0xbd, 0xf5, 0xb2, 0xc9, 0xbc, 0x9d, 0x79, 0xfb, 0xe6, 0xcd, 0x6e, 0x02, 0x3b, 0x61, 0xda, 0x2f, 0xd8, 0xb1, 0x71, 0x72, 0x8f, 0xef, 0x3d, 0x73, 0xee, 0xb9, 0x33, 0x63, 0xd8, 0xf1, 0xa2,
0xef, 0xa7, 0x89, 0xc8, 0x78, 0x88, 0x5b, 0xe9, 0xe9, 0x47, 0x0c, 0xe5, 0x96, 0xcc, 0x11, 0xf5, 0xe1, 0x30, 0x0a, 0x45, 0xcc, 0x3d, 0xdc, 0x8a, 0xce, 0x3e, 0xa2, 0x27, 0xb7, 0x64, 0x82, 0xa8,
0x12, 0x76, 0x79, 0x72, 0x86, 0x59, 0x9e, 0xca, 0x74, 0x4b, 0xaf, 0xc2, 0x80, 0x37, 0x35, 0x42, 0x1e, 0x5e, 0x9f, 0x87, 0x17, 0x18, 0x27, 0x91, 0x8c, 0xb6, 0xd4, 0x53, 0x94, 0xe0, 0x4d, 0x85,
0x61, 0x8a, 0xf8, 0xbf, 0x08, 0x00, 0x4b, 0x53, 0xb9, 0xa7, 0x43, 0x7a, 0x07, 0x16, 0x79, 0xd8, 0x50, 0x98, 0x22, 0xce, 0x35, 0x01, 0x60, 0x51, 0x24, 0xf7, 0x54, 0x48, 0xff, 0x83, 0x45, 0xee,
0x0b, 0x90, 0x47, 0x87, 0x91, 0x43, 0x3c, 0xd2, 0x59, 0x64, 0x53, 0x80, 0x3a, 0xd0, 0xd2, 0xa7, 0x0d, 0x5c, 0xe4, 0x7e, 0xcf, 0x37, 0x89, 0x4d, 0xba, 0x8b, 0x6c, 0x0a, 0x50, 0x13, 0x0c, 0xb5,
0x1e, 0x46, 0x8e, 0xad, 0xf7, 0xca, 0x90, 0xba, 0x00, 0x05, 0xe1, 0xc9, 0x30, 0x43, 0xa7, 0xa1, 0x6a, 0xcf, 0x37, 0x75, 0xf5, 0xae, 0x08, 0xa9, 0x05, 0x90, 0x11, 0x9e, 0x8c, 0x63, 0x34, 0x5b,
0x37, 0x0d, 0x44, 0xf1, 0xca, 0xb8, 0x8f, 0x42, 0xf2, 0x7e, 0xe6, 0x34, 0x3d, 0xd2, 0x69, 0xb0, 0xea, 0x65, 0x09, 0x49, 0x79, 0x65, 0x30, 0x44, 0x21, 0xf9, 0x30, 0x36, 0xdb, 0x36, 0xe9, 0xb6,
0x29, 0x40, 0x29, 0x34, 0x05, 0x62, 0xe4, 0xcc, 0x79, 0xa4, 0xd3, 0x66, 0xfa, 0x3b, 0xdd, 0x80, 0xd8, 0x14, 0xa0, 0x14, 0xda, 0x02, 0xd1, 0x37, 0xe7, 0x6c, 0xd2, 0xed, 0x30, 0xf5, 0x9f, 0x6e,
0x85, 0x38, 0xc2, 0x44, 0xc6, 0x72, 0xe8, 0xcc, 0x6b, 0x7c, 0x12, 0xfb, 0x3f, 0x6d, 0x80, 0x93, 0xc0, 0x42, 0xe0, 0x63, 0x28, 0x03, 0x39, 0x36, 0xe7, 0x15, 0x3e, 0x89, 0xe9, 0x43, 0x58, 0xce,
0x1c, 0x71, 0x2c, 0xda, 0x83, 0x25, 0xd5, 0x51, 0x21, 0x52, 0x38, 0xc4, 0x6b, 0x74, 0x16, 0x99, 0xb8, 0x8f, 0xf8, 0x78, 0x10, 0x71, 0xdf, 0x34, 0x54, 0x42, 0x15, 0x74, 0x7e, 0xea, 0x00, 0x27,
0x09, 0x55, 0xdb, 0xb2, 0xeb, 0x6d, 0xdd, 0x87, 0x15, 0x91, 0xf0, 0x4c, 0x74, 0x53, 0xb9, 0xcb, 0x09, 0x62, 0xde, 0x9a, 0x0d, 0x4b, 0x69, 0xdf, 0x59, 0x2b, 0xc2, 0x24, 0x76, 0xab, 0xbb, 0xc8,
0x85, 0xea, 0xae, 0x68, 0xa0, 0x86, 0xaa, 0x73, 0x8a, 0x96, 0xc4, 0x73, 0x2e, 0xb9, 0x6e, 0xa3, 0xca, 0x50, 0xb5, 0x79, 0xbd, 0xde, 0xfc, 0x23, 0x58, 0x11, 0x21, 0x8f, 0x45, 0x3f, 0x92, 0xbb,
0xcd, 0x4c, 0x88, 0x6e, 0x02, 0x0d, 0x07, 0x79, 0x8e, 0x89, 0x64, 0xc8, 0xa3, 0x23, 0x1c, 0x06, 0x5c, 0xa4, 0x1e, 0x64, 0x6d, 0xd6, 0xd0, 0x74, 0x9d, 0x4c, 0x87, 0x78, 0xc5, 0x25, 0x57, 0xcd,
0x5c, 0x74, 0x75, 0x5b, 0x4d, 0x36, 0x63, 0xa7, 0x6a, 0xcb, 0x7c, 0xdd, 0x16, 0xd3, 0x82, 0x56, 0x76, 0x58, 0x19, 0xa2, 0x9b, 0x40, 0xbd, 0x51, 0x92, 0x60, 0x28, 0x19, 0x72, 0xff, 0x10, 0xc7,
0xd5, 0x02, 0x65, 0x78, 0x2c, 0x8e, 0xc7, 0xfa, 0x9c, 0x05, 0x8f, 0x74, 0x16, 0x98, 0x81, 0xf8, 0x2e, 0x17, 0x7d, 0xd5, 0x7c, 0x9b, 0x35, 0xbc, 0xa9, 0x9a, 0x37, 0x5f, 0x37, 0xaf, 0x6c, 0x94,
0x2f, 0x60, 0x99, 0xf1, 0x73, 0xc3, 0x24, 0x07, 0x5a, 0x19, 0x1f, 0xf6, 0x52, 0x5e, 0xcc, 0xb5, 0x51, 0x33, 0xca, 0x02, 0x08, 0xc4, 0x71, 0xae, 0xcf, 0x5c, 0xb0, 0x49, 0x77, 0x81, 0x95, 0x10,
0xcd, 0xca, 0x50, 0x89, 0x10, 0xf1, 0x59, 0xc2, 0xe5, 0x20, 0x47, 0x6d, 0x4e, 0x9b, 0x4d, 0x01, 0xe7, 0x35, 0x2c, 0x33, 0x7e, 0x59, 0x32, 0xc9, 0x04, 0x23, 0xce, 0x3d, 0x25, 0x8a, 0xab, 0x08,
0x7f, 0x0f, 0xd6, 0x2a, 0x44, 0xef, 0x62, 0xd9, 0x3d, 0xd4, 0x45, 0x39, 0x3f, 0x2f, 0xa0, 0x31, 0x53, 0x11, 0x22, 0xb8, 0x08, 0xb9, 0x1c, 0x25, 0xa8, 0xcc, 0xe9, 0xb0, 0x29, 0xe0, 0xec, 0xc1,
0xe1, 0x14, 0xa0, 0x2b, 0x60, 0xc7, 0xa5, 0xd1, 0x76, 0x1c, 0xf9, 0xdf, 0x09, 0xac, 0x2a, 0x8a, 0x5a, 0x85, 0xe8, 0x7d, 0x20, 0xfb, 0x3d, 0x55, 0x94, 0xf0, 0xcb, 0x0c, 0xca, 0x09, 0xa7, 0x00,
0xe3, 0x61, 0x12, 0xbe, 0x44, 0x21, 0xf8, 0x19, 0xd2, 0x27, 0xd0, 0x0a, 0xd3, 0x44, 0x62, 0x22, 0x5d, 0x01, 0x3d, 0x28, 0x8c, 0xd6, 0x03, 0xdf, 0xf9, 0x4e, 0x60, 0x35, 0xa5, 0x38, 0x1e, 0x87,
0x75, 0xfd, 0xd2, 0xb6, 0xb7, 0x69, 0xdc, 0xd4, 0x32, 0x7b, 0xaf, 0x48, 0x79, 0xcb, 0x7b, 0x03, 0xde, 0x1b, 0x14, 0x82, 0x5f, 0x20, 0x7d, 0x0e, 0x86, 0x17, 0x85, 0x12, 0x43, 0xa9, 0xea, 0x97,
0x64, 0x65, 0x01, 0xdd, 0x01, 0xc8, 0x27, 0x97, 0x56, 0x9f, 0xb3, 0xb4, 0x7d, 0xcf, 0x2c, 0x9f, 0xb6, 0xed, 0xcd, 0xd2, 0x7e, 0x2e, 0xb2, 0xf7, 0xb2, 0x94, 0x53, 0x3e, 0x18, 0x21, 0x2b, 0x0a,
0x21, 0x99, 0x19, 0x25, 0xfe, 0x6f, 0x1b, 0xd6, 0x67, 0x1d, 0x41, 0x9f, 0x02, 0x74, 0x91, 0x47, 0xe8, 0x0e, 0x40, 0x32, 0xd9, 0xda, 0x6a, 0x9d, 0xa5, 0xed, 0x07, 0xe5, 0xf2, 0x06, 0xc9, 0xac,
0x6f, 0xb2, 0x88, 0x4b, 0x1c, 0x0b, 0xdb, 0xa8, 0x0b, 0x0b, 0x26, 0x19, 0x81, 0xc5, 0x8c, 0x7c, 0x54, 0xe2, 0xfc, 0xd2, 0x61, 0xbd, 0x69, 0x09, 0xfa, 0x02, 0xa0, 0x8f, 0xdc, 0x7f, 0x17, 0xfb,
0x7a, 0x04, 0xab, 0x1f, 0x06, 0xbd, 0x9e, 0x62, 0x65, 0xf8, 0x69, 0x80, 0x42, 0xce, 0x12, 0xa7, 0x5c, 0x62, 0x2e, 0x6c, 0xa3, 0x2e, 0xcc, 0x9d, 0x64, 0xb8, 0x1a, 0x2b, 0xe5, 0xd3, 0x43, 0x58,
0x28, 0x0e, 0xaa, 0x69, 0x81, 0xc5, 0xea, 0x95, 0xf4, 0x15, 0xdc, 0x9a, 0x42, 0x22, 0x4b, 0x13, 0x3d, 0x1f, 0x0d, 0x06, 0x29, 0x2b, 0xc3, 0x4f, 0x23, 0x14, 0xb2, 0x49, 0x5c, 0x4a, 0x71, 0x50,
0x51, 0xbc, 0xac, 0x19, 0x4e, 0x1d, 0xd4, 0xf2, 0x02, 0x8b, 0x5d, 0xa9, 0xa5, 0xfb, 0xb0, 0x8c, 0x4d, 0x73, 0x35, 0x56, 0xaf, 0xa4, 0x6f, 0xe1, 0x9f, 0x29, 0x24, 0xe2, 0x28, 0x14, 0xd9, 0xf9,
0x79, 0x9e, 0xe6, 0x13, 0xb2, 0xa6, 0x26, 0xbb, 0x5b, 0x27, 0xdb, 0x37, 0x93, 0x02, 0x8b, 0x55, 0x6b, 0x70, 0xea, 0xa0, 0x96, 0xe7, 0x6a, 0x6c, 0xa6, 0x96, 0xee, 0xc3, 0x32, 0x26, 0x49, 0x94,
0xab, 0x76, 0x5b, 0x30, 0xf7, 0x59, 0x59, 0xe5, 0x7f, 0x21, 0xb0, 0x52, 0x75, 0x83, 0xae, 0xc3, 0x4c, 0xc8, 0xda, 0x8a, 0xec, 0xff, 0x3a, 0xd9, 0x7e, 0x39, 0xc9, 0xd5, 0x58, 0xb5, 0x6a, 0xd7,
0x9c, 0x72, 0xa3, 0x7c, 0x83, 0x45, 0x40, 0x1f, 0x43, 0x6b, 0xfc, 0x48, 0x1c, 0xdb, 0x6b, 0x5c, 0x80, 0xb9, 0xcf, 0xa9, 0x55, 0xce, 0x17, 0x02, 0x2b, 0x55, 0x37, 0xe8, 0x3a, 0xcc, 0xa5, 0x6e,
0x67, 0x54, 0x65, 0x3e, 0xf5, 0xa1, 0x5d, 0x3e, 0xc2, 0xd7, 0x5c, 0x76, 0x9d, 0x86, 0xe6, 0xad, 0x14, 0x67, 0x30, 0x0b, 0xe8, 0x33, 0x30, 0xf2, 0x43, 0x62, 0xea, 0x76, 0xeb, 0x2e, 0xa3, 0x2a,
0x60, 0xfe, 0x57, 0x02, 0x6b, 0x33, 0x2c, 0xbd, 0x19, 0x31, 0xdf, 0x48, 0x71, 0xb1, 0xea, 0x13, 0xf2, 0xa9, 0x03, 0x9d, 0xe2, 0x10, 0x1e, 0x71, 0xd9, 0x37, 0x5b, 0x8a, 0xb7, 0x82, 0x39, 0x5f,
0xb9, 0x19, 0x35, 0x0f, 0xe1, 0xf6, 0x95, 0x89, 0x2a, 0x25, 0x7a, 0xa2, 0xe3, 0xdf, 0xf7, 0x22, 0x09, 0xac, 0x35, 0x58, 0x7a, 0x3f, 0x62, 0xbe, 0x91, 0x6c, 0x63, 0xd5, 0x27, 0x72, 0x3f, 0x6a,
0xd8, 0x7d, 0xf6, 0xe7, 0xd2, 0x25, 0x17, 0x97, 0x2e, 0xf9, 0x77, 0xe9, 0x92, 0x1f, 0x23, 0xd7, 0x9e, 0xc0, 0xbf, 0x33, 0x13, 0x4d, 0x95, 0xa8, 0x89, 0xe6, 0x5f, 0x81, 0x2c, 0x70, 0x4e, 0xb3,
0xba, 0x18, 0xb9, 0xd6, 0xdf, 0x91, 0x6b, 0xbd, 0x7f, 0x70, 0xcd, 0xff, 0x9b, 0xd3, 0x79, 0xfd, 0x61, 0x66, 0x6b, 0xf5, 0xc2, 0xf3, 0xa8, 0x76, 0xf3, 0x93, 0x99, 0x9b, 0x7f, 0xe6, 0xae, 0xd6,
0xf1, 0xe8, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4e, 0xa5, 0xe2, 0x7c, 0xa1, 0x06, 0x00, 0x00, 0x1b, 0xee, 0xea, 0xdd, 0x97, 0xbf, 0x6f, 0x2c, 0x72, 0x75, 0x63, 0x91, 0x3f, 0x37, 0x16, 0xf9,
0x71, 0x6b, 0x69, 0x57, 0xb7, 0x96, 0x76, 0x7d, 0x6b, 0x69, 0x1f, 0x1e, 0xdf, 0xf1, 0x6b, 0x77,
0x36, 0xaf, 0x7e, 0x9e, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x24, 0x93, 0x3b, 0x00, 0x1f, 0x07,
0x00, 0x00,
} }
func (m *RootChange) Marshal() (dAtA []byte, err error) { func (m *RootChange) Marshal() (dAtA []byte, err error) {
@ -807,6 +873,13 @@ func (m *RootChange) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.ChangePayload) > 0 {
i -= len(m.ChangePayload)
copy(dAtA[i:], m.ChangePayload)
i = encodeVarintTreechange(dAtA, i, uint64(len(m.ChangePayload)))
i--
dAtA[i] = 0x3a
}
if len(m.Identity) > 0 { if len(m.Identity) > 0 {
i -= len(m.Identity) i -= len(m.Identity)
copy(dAtA[i:], m.Identity) copy(dAtA[i:], m.Identity)
@ -1362,6 +1435,43 @@ func (m *TreeErrorResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
func (m *TreeChangeInfo) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *TreeChangeInfo) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *TreeChangeInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.ChangePayload) > 0 {
i -= len(m.ChangePayload)
copy(dAtA[i:], m.ChangePayload)
i = encodeVarintTreechange(dAtA, i, uint64(len(m.ChangePayload)))
i--
dAtA[i] = 0x12
}
if len(m.ChangeType) > 0 {
i -= len(m.ChangeType)
copy(dAtA[i:], m.ChangeType)
i = encodeVarintTreechange(dAtA, i, uint64(len(m.ChangeType)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintTreechange(dAtA []byte, offset int, v uint64) int { func encodeVarintTreechange(dAtA []byte, offset int, v uint64) int {
offset -= sovTreechange(v) offset -= sovTreechange(v)
base := offset base := offset
@ -1402,6 +1512,10 @@ func (m *RootChange) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovTreechange(uint64(l)) n += 1 + l + sovTreechange(uint64(l))
} }
l = len(m.ChangePayload)
if l > 0 {
n += 1 + l + sovTreechange(uint64(l))
}
return n return n
} }
@ -1650,6 +1764,23 @@ func (m *TreeErrorResponse) Size() (n int) {
return n return n
} }
func (m *TreeChangeInfo) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.ChangeType)
if l > 0 {
n += 1 + l + sovTreechange(uint64(l))
}
l = len(m.ChangePayload)
if l > 0 {
n += 1 + l + sovTreechange(uint64(l))
}
return n
}
func sovTreechange(x uint64) (n int) { func sovTreechange(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7 return (math_bits.Len64(x|1) + 6) / 7
} }
@ -1868,6 +1999,40 @@ func (m *RootChange) Unmarshal(dAtA []byte) error {
m.Identity = []byte{} m.Identity = []byte{}
} }
iNdEx = postIndex iNdEx = postIndex
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ChangePayload", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTreechange
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthTreechange
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthTreechange
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ChangePayload = append(m.ChangePayload[:0], dAtA[iNdEx:postIndex]...)
if m.ChangePayload == nil {
m.ChangePayload = []byte{}
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipTreechange(dAtA[iNdEx:]) skippy, err := skipTreechange(dAtA[iNdEx:])
@ -3233,6 +3398,122 @@ func (m *TreeErrorResponse) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *TreeChangeInfo) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTreechange
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: TreeChangeInfo: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TreeChangeInfo: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ChangeType", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTreechange
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTreechange
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTreechange
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ChangeType = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ChangePayload", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTreechange
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthTreechange
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthTreechange
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ChangePayload = append(m.ChangePayload[:0], dAtA[iNdEx:postIndex]...)
if m.ChangePayload == nil {
m.ChangePayload = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTreechange(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTreechange
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipTreechange(dAtA []byte) (n int, err error) { func skipTreechange(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0

View File

@ -3,7 +3,6 @@ package objectsync
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/anytypeio/any-sync/app/ocache"
"github.com/anytypeio/any-sync/commonspace/objectsync/synchandler" "github.com/anytypeio/any-sync/commonspace/objectsync/synchandler"
"github.com/anytypeio/any-sync/commonspace/peermanager" "github.com/anytypeio/any-sync/commonspace/peermanager"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto" "github.com/anytypeio/any-sync/commonspace/spacesyncproto"
@ -15,9 +14,13 @@ import (
"time" "time"
) )
type LastUsage interface {
LastUsage() time.Time
}
// MessagePool can be made generic to work with different streams // MessagePool can be made generic to work with different streams
type MessagePool interface { type MessagePool interface {
ocache.ObjectLastUsage LastUsage
synchandler.SyncHandler synchandler.SyncHandler
peermanager.PeerManager peermanager.PeerManager
SendSync(ctx context.Context, peerId string, message *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error) SendSync(ctx context.Context, peerId string, message *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error)

View File

@ -6,7 +6,6 @@ import (
"time" "time"
"github.com/anytypeio/any-sync/app/logger" "github.com/anytypeio/any-sync/app/logger"
"github.com/anytypeio/any-sync/app/ocache"
"github.com/anytypeio/any-sync/commonspace/object/syncobjectgetter" "github.com/anytypeio/any-sync/commonspace/object/syncobjectgetter"
"github.com/anytypeio/any-sync/commonspace/objectsync/synchandler" "github.com/anytypeio/any-sync/commonspace/objectsync/synchandler"
"github.com/anytypeio/any-sync/commonspace/peermanager" "github.com/anytypeio/any-sync/commonspace/peermanager"
@ -20,7 +19,7 @@ import (
var log = logger.NewNamed("common.commonspace.objectsync") var log = logger.NewNamed("common.commonspace.objectsync")
type ObjectSync interface { type ObjectSync interface {
ocache.ObjectLastUsage LastUsage
synchandler.SyncHandler synchandler.SyncHandler
MessagePool() MessagePool MessagePool() MessagePool

View File

@ -14,8 +14,8 @@ import (
) )
const ( const (
SpaceSettingsChangeType = "reserved.spacesettings" SpaceReserved = "any-sync.space"
SpaceDerivationScheme = "derivation.standard" SpaceDerivationScheme = "derivation.standard"
) )
func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload spacestorage.SpaceStorageCreatePayload, err error) { func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload spacestorage.SpaceStorageCreatePayload, err error) {
@ -36,11 +36,12 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp
return return
} }
header := &spacesyncproto.SpaceHeader{ header := &spacesyncproto.SpaceHeader{
Identity: identity, Identity: identity,
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().Unix(),
SpaceType: payload.SpaceType, SpaceType: payload.SpaceType,
ReplicationKey: payload.ReplicationKey, SpaceHeaderPayload: payload.SpacePayload,
Seed: spaceHeaderSeed, ReplicationKey: payload.ReplicationKey,
Seed: spaceHeaderSeed,
} }
marshalled, err := header.Marshal() marshalled, err := header.Marshal()
if err != nil { if err != nil {
@ -81,7 +82,7 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp
SpaceId: spaceId, SpaceId: spaceId,
EncryptedReadKey: encReadKey, EncryptedReadKey: encReadKey,
CurrentReadKeyHash: readKeyHash, CurrentReadKeyHash: readKeyHash,
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().Unix(),
} }
rawWithId, err := marshalAclRoot(aclRoot, payload.SigningKey) rawWithId, err := marshalAclRoot(aclRoot, payload.SigningKey)
if err != nil { if err != nil {
@ -101,8 +102,8 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp
SigningKey: payload.SigningKey, SigningKey: payload.SigningKey,
SpaceId: spaceId, SpaceId: spaceId,
Seed: spaceSettingsSeed, Seed: spaceSettingsSeed,
ChangeType: SpaceSettingsChangeType, ChangeType: SpaceReserved,
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().Unix(),
}) })
if err != nil { if err != nil {
return return
@ -146,9 +147,10 @@ func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload sp
// preparing header and space id // preparing header and space id
header := &spacesyncproto.SpaceHeader{ header := &spacesyncproto.SpaceHeader{
Identity: identity, Identity: identity,
SpaceType: SpaceTypeDerived, SpaceType: payload.SpaceType,
ReplicationKey: repKey, SpaceHeaderPayload: payload.SpacePayload,
ReplicationKey: repKey,
} }
marshalled, err := header.Marshal() marshalled, err := header.Marshal()
if err != nil { if err != nil {
@ -201,7 +203,7 @@ func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload sp
Identity: aclRoot.Identity, Identity: aclRoot.Identity,
SigningKey: payload.SigningKey, SigningKey: payload.SigningKey,
SpaceId: spaceId, SpaceId: spaceId,
ChangeType: SpaceSettingsChangeType, ChangeType: SpaceReserved,
}) })
if err != nil { if err != nil {
return return

View File

@ -48,7 +48,7 @@ func (s *stateBuilder) Build(tr objecttree.ObjectTree, oldState *State) (state *
func (s *stateBuilder) processChange(change *objecttree.Change, rootId string, state *State) *State { func (s *stateBuilder) processChange(change *objecttree.Change, rootId string, state *State) *State {
// ignoring root change which has empty model or startId change // ignoring root change which has empty model or startId change
if change.Model == nil || state.LastIteratedId == change.Id { if len(change.PreviousIds) == 0 || state.LastIteratedId == change.Id {
return state return state
} }

View File

@ -42,6 +42,7 @@ func TestStateBuilder_ProcessChange(t *testing.T) {
t.Run("changeId is equal to rootId", func(t *testing.T) { t.Run("changeId is equal to rootId", func(t *testing.T) {
ch := &objecttree.Change{} ch := &objecttree.Change{}
ch.PreviousIds = []string{"someId"}
ch.Model = &spacesyncproto.SettingsData{ ch.Model = &spacesyncproto.SettingsData{
Snapshot: &spacesyncproto.SpaceSettingsSnapshot{ Snapshot: &spacesyncproto.SpaceSettingsSnapshot{
DeletedIds: []string{"id1", "id2"}, DeletedIds: []string{"id1", "id2"},
@ -56,6 +57,7 @@ func TestStateBuilder_ProcessChange(t *testing.T) {
t.Run("changeId is not equal to lastIteratedId or rootId", func(t *testing.T) { t.Run("changeId is not equal to lastIteratedId or rootId", func(t *testing.T) {
ch := &objecttree.Change{} ch := &objecttree.Change{}
ch.PreviousIds = []string{"someId"}
ch.Model = &spacesyncproto.SettingsData{ ch.Model = &spacesyncproto.SettingsData{
Content: []*spacesyncproto.SpaceSettingsContent{ Content: []*spacesyncproto.SpaceSettingsContent{
{Value: &spacesyncproto.SpaceSettingsContent_ObjectDelete{ {Value: &spacesyncproto.SpaceSettingsContent_ObjectDelete{

View File

@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"github.com/anytypeio/any-sync/accountservice" "github.com/anytypeio/any-sync/accountservice"
"github.com/anytypeio/any-sync/app/logger" "github.com/anytypeio/any-sync/app/logger"
"github.com/anytypeio/any-sync/app/ocache"
"github.com/anytypeio/any-sync/commonspace/headsync" "github.com/anytypeio/any-sync/commonspace/headsync"
"github.com/anytypeio/any-sync/commonspace/object/acl/list" "github.com/anytypeio/any-sync/commonspace/object/acl/list"
"github.com/anytypeio/any-sync/commonspace/object/acl/syncacl" "github.com/anytypeio/any-sync/commonspace/object/acl/syncacl"
@ -52,6 +51,8 @@ type SpaceCreatePayload struct {
ReadKey []byte ReadKey []byte
// ReplicationKey is a key which is to be used to determine the node where the space should be held // ReplicationKey is a key which is to be used to determine the node where the space should be held
ReplicationKey uint64 ReplicationKey uint64
// SpacePayload is an arbitrary payload related to space type
SpacePayload []byte
} }
type HandleMessage struct { type HandleMessage struct {
@ -61,11 +62,11 @@ type HandleMessage struct {
Message *spacesyncproto.ObjectSyncMessage Message *spacesyncproto.ObjectSyncMessage
} }
const SpaceTypeDerived = "derived.space"
type SpaceDerivePayload struct { type SpaceDerivePayload struct {
SigningKey signingkey.PrivKey SigningKey signingkey.PrivKey
EncryptionKey encryptionkey.PrivKey EncryptionKey encryptionkey.PrivKey
SpaceType string
SpacePayload []byte
} }
type SpaceDescription struct { type SpaceDescription struct {
@ -81,9 +82,6 @@ func NewSpaceId(id string, repKey uint64) string {
} }
type Space interface { type Space interface {
ocache.ObjectLocker
ocache.ObjectLastUsage
Id() string Id() string
Init(ctx context.Context) error Init(ctx context.Context) error
@ -108,6 +106,7 @@ type Space interface {
HandleMessage(ctx context.Context, msg HandleMessage) (err error) HandleMessage(ctx context.Context, msg HandleMessage) (err error)
TryClose(objectTTL time.Duration) (close bool, err error)
Close() error Close() error
} }
@ -134,16 +133,6 @@ type space struct {
treesUsed *atomic.Int32 treesUsed *atomic.Int32
} }
func (s *space) LastUsage() time.Time {
return s.objectSync.LastUsage()
}
func (s *space) Locked() bool {
locked := s.treesUsed.Load() > 1
log.With(zap.Int32("trees used", s.treesUsed.Load()), zap.Bool("locked", locked), zap.String("spaceId", s.id)).Debug("space lock status check")
return locked
}
func (s *space) Id() string { func (s *space) Id() string {
return s.id return s.id
} }
@ -462,3 +451,15 @@ func (s *space) Close() error {
log.With(zap.String("id", s.id)).Debug("space closed") log.With(zap.String("id", s.id)).Debug("space closed")
return mError.Err() return mError.Err()
} }
func (s *space) TryClose(objectTTL time.Duration) (close bool, err error) {
if time.Now().Sub(s.objectSync.LastUsage()) < objectTTL {
return false, nil
}
locked := s.treesUsed.Load() > 1
log.With(zap.Int32("trees used", s.treesUsed.Load()), zap.Bool("locked", locked), zap.String("spaceId", s.id)).Debug("space lock status check")
if locked {
return false, nil
}
return true, s.Close()
}

View File

@ -98,6 +98,7 @@ message SpaceHeader {
string spaceType = 3; string spaceType = 3;
uint64 replicationKey = 4; uint64 replicationKey = 4;
bytes seed = 5; bytes seed = 5;
bytes spaceHeaderPayload = 6;
} }
// RawSpaceHeader is raw header for SpaceHeader // RawSpaceHeader is raw header for SpaceHeader

View File

@ -694,11 +694,12 @@ func (m *SpacePayload) GetSpaceSettingsPayloadId() string {
// SpaceHeader is a header for a space // SpaceHeader is a header for a space
type SpaceHeader struct { type SpaceHeader struct {
Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
SpaceType string `protobuf:"bytes,3,opt,name=spaceType,proto3" json:"spaceType,omitempty"` SpaceType string `protobuf:"bytes,3,opt,name=spaceType,proto3" json:"spaceType,omitempty"`
ReplicationKey uint64 `protobuf:"varint,4,opt,name=replicationKey,proto3" json:"replicationKey,omitempty"` ReplicationKey uint64 `protobuf:"varint,4,opt,name=replicationKey,proto3" json:"replicationKey,omitempty"`
Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"` Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"`
SpaceHeaderPayload []byte `protobuf:"bytes,6,opt,name=spaceHeaderPayload,proto3" json:"spaceHeaderPayload,omitempty"`
} }
func (m *SpaceHeader) Reset() { *m = SpaceHeader{} } func (m *SpaceHeader) Reset() { *m = SpaceHeader{} }
@ -769,6 +770,13 @@ func (m *SpaceHeader) GetSeed() []byte {
return nil return nil
} }
func (m *SpaceHeader) GetSpaceHeaderPayload() []byte {
if m != nil {
return m.SpaceHeaderPayload
}
return nil
}
// RawSpaceHeader is raw header for SpaceHeader // RawSpaceHeader is raw header for SpaceHeader
type RawSpaceHeader struct { type RawSpaceHeader struct {
SpaceHeader []byte `protobuf:"bytes,1,opt,name=spaceHeader,proto3" json:"spaceHeader,omitempty"` SpaceHeader []byte `protobuf:"bytes,1,opt,name=spaceHeader,proto3" json:"spaceHeader,omitempty"`
@ -1240,72 +1248,73 @@ func init() {
} }
var fileDescriptor_80e49f1f4ac27799 = []byte{ var fileDescriptor_80e49f1f4ac27799 = []byte{
// 1030 bytes of a gzipped FileDescriptorProto // 1042 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x4b, 0x6f, 0xdb, 0x46, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
0x10, 0x16, 0xe9, 0xa7, 0xc6, 0xb2, 0xcc, 0x6c, 0x9c, 0x44, 0x55, 0x0c, 0x45, 0x58, 0x14, 0x85, 0x14, 0xf7, 0x6e, 0xd2, 0x24, 0x7e, 0x71, 0x9c, 0xed, 0x34, 0x6d, 0x8d, 0x1b, 0xb9, 0xd6, 0x08,
0x91, 0x43, 0x1e, 0x72, 0x51, 0x20, 0x69, 0x7b, 0x48, 0x64, 0xa7, 0x11, 0x8a, 0xd4, 0xc6, 0xaa, 0xa1, 0xa8, 0x87, 0xb4, 0x75, 0x10, 0x52, 0x0b, 0x1c, 0x5a, 0x27, 0xa5, 0x16, 0x2a, 0x89, 0xc6,
0x41, 0x81, 0x02, 0x39, 0xac, 0xc9, 0xb1, 0xc4, 0x96, 0x22, 0x59, 0xee, 0xaa, 0xb6, 0x8e, 0x3d, 0x54, 0x48, 0x48, 0x3d, 0x4c, 0x76, 0x5f, 0xec, 0x85, 0xf5, 0xee, 0xb2, 0x33, 0x26, 0xf1, 0x91,
0xf5, 0xda, 0x73, 0x7b, 0xea, 0x7f, 0xe8, 0x8f, 0xe8, 0x31, 0xc7, 0x1e, 0x0b, 0xfb, 0x8f, 0x14, 0x13, 0x57, 0xce, 0xf0, 0x35, 0xf8, 0x10, 0x1c, 0xcb, 0x8d, 0x23, 0x4a, 0xbe, 0x08, 0x9a, 0xd9,
0xbb, 0x5c, 0x3e, 0x24, 0x51, 0x01, 0x7a, 0x91, 0xb9, 0xdf, 0xcc, 0x7c, 0xf3, 0xda, 0x9d, 0x31, 0xd9, 0x3f, 0xb6, 0xd7, 0x95, 0xb8, 0x38, 0x3b, 0xbf, 0xf7, 0xde, 0xef, 0xfd, 0x9b, 0x79, 0x2f,
0x3c, 0x75, 0xa3, 0xc9, 0x24, 0x0a, 0x45, 0xcc, 0x5d, 0x7c, 0xac, 0x7f, 0xc5, 0x2c, 0x74, 0xe3, 0xf0, 0xd4, 0x8d, 0x26, 0x93, 0x28, 0x14, 0x31, 0x77, 0xf1, 0xb1, 0xfe, 0x15, 0xb3, 0xd0, 0x8d,
0x24, 0x92, 0xd1, 0x63, 0xfd, 0x2b, 0x0a, 0xf4, 0x91, 0x06, 0x48, 0x3d, 0x07, 0xe8, 0x00, 0x76, 0x93, 0x48, 0x46, 0x8f, 0xf5, 0xaf, 0x28, 0xd0, 0x43, 0x0d, 0x90, 0x7a, 0x0e, 0xd0, 0x01, 0xec,
0x5f, 0x23, 0xf7, 0x86, 0xb3, 0xd0, 0x65, 0x3c, 0x1c, 0x21, 0x21, 0xb0, 0x7e, 0x91, 0x44, 0x93, 0xbc, 0x46, 0xee, 0x0d, 0x67, 0xa1, 0xcb, 0x78, 0x38, 0x42, 0x42, 0x60, 0xfd, 0x22, 0x89, 0x26,
0x96, 0xd5, 0xb5, 0x0e, 0xd7, 0x99, 0xfe, 0x26, 0x4d, 0xb0, 0x65, 0xd4, 0xb2, 0x35, 0x62, 0xcb, 0x2d, 0xab, 0x6b, 0x1d, 0xac, 0x33, 0xfd, 0x4d, 0x9a, 0x60, 0xcb, 0xa8, 0x65, 0x6b, 0xc4, 0x96,
0x88, 0xec, 0xc3, 0x46, 0xe0, 0x4f, 0x7c, 0xd9, 0x5a, 0xeb, 0x5a, 0x87, 0xbb, 0x2c, 0x3d, 0xd0, 0x11, 0xd9, 0x83, 0x5b, 0x81, 0x3f, 0xf1, 0x65, 0x6b, 0xad, 0x6b, 0x1d, 0xec, 0xb0, 0xf4, 0x40,
0x2b, 0x68, 0xe6, 0x54, 0x28, 0xa6, 0x81, 0x54, 0x5c, 0x63, 0x2e, 0xc6, 0x9a, 0xab, 0xc1, 0xf4, 0xaf, 0xa0, 0x99, 0x53, 0xa1, 0x98, 0x06, 0x52, 0x71, 0x8d, 0xb9, 0x18, 0x6b, 0xae, 0x06, 0xd3,
0x37, 0xf9, 0x02, 0xb6, 0x31, 0xc0, 0x09, 0x86, 0x52, 0xb4, 0xec, 0xee, 0xda, 0xe1, 0x4e, 0xaf, 0xdf, 0xe4, 0x0b, 0xd8, 0xc2, 0x00, 0x27, 0x18, 0x4a, 0xd1, 0xb2, 0xbb, 0x6b, 0x07, 0xdb, 0xbd,
0xfb, 0xa8, 0x88, 0x6f, 0x9e, 0xe0, 0x24, 0x55, 0x64, 0xb9, 0x85, 0xf2, 0xec, 0x46, 0xd3, 0x30, 0xee, 0x61, 0x11, 0xdf, 0x3c, 0xc1, 0x49, 0xaa, 0xc8, 0x72, 0x0b, 0xe5, 0xd9, 0x8d, 0xa6, 0x61,
0xf7, 0xac, 0x0f, 0xf4, 0x73, 0xb8, 0x53, 0x69, 0xa8, 0x02, 0xf7, 0x3d, 0xed, 0xbe, 0xce, 0x6c, 0xee, 0x59, 0x1f, 0xe8, 0xe7, 0x70, 0xb7, 0xd2, 0x50, 0x05, 0xee, 0x7b, 0xda, 0x7d, 0x9d, 0xd9,
0xdf, 0xd3, 0x01, 0x21, 0xf7, 0x74, 0x2a, 0x75, 0xa6, 0xbf, 0xe9, 0x3b, 0xd8, 0x2b, 0x8c, 0x7f, 0xbe, 0xa7, 0x03, 0x42, 0xee, 0xe9, 0x54, 0xea, 0x4c, 0x7f, 0xd3, 0x77, 0xb0, 0x5b, 0x18, 0xff,
0x9a, 0xa2, 0x90, 0xa4, 0x05, 0x5b, 0x3a, 0xa4, 0x41, 0x66, 0x9b, 0x1d, 0xc9, 0x13, 0xd8, 0x4c, 0x34, 0x45, 0x21, 0x49, 0x0b, 0x36, 0x75, 0x48, 0x83, 0xcc, 0x36, 0x3b, 0x92, 0x27, 0xb0, 0x91,
0x54, 0x99, 0xb2, 0xd8, 0x5b, 0x55, 0xb1, 0x2b, 0x05, 0x66, 0xf4, 0xe8, 0x57, 0xe0, 0x94, 0x62, 0xa8, 0x32, 0x65, 0xb1, 0xb7, 0xaa, 0x62, 0x57, 0x0a, 0xcc, 0xe8, 0xd1, 0xaf, 0xc0, 0x29, 0xc5,
0x8b, 0xa3, 0x50, 0x20, 0x39, 0x82, 0xad, 0x44, 0xc7, 0x29, 0x5a, 0x96, 0xa6, 0xf9, 0x68, 0x65, 0x16, 0x47, 0xa1, 0x40, 0x72, 0x04, 0x9b, 0x89, 0x8e, 0x53, 0xb4, 0x2c, 0x4d, 0xf3, 0xd1, 0xca,
0x09, 0x58, 0xa6, 0x49, 0xff, 0xb0, 0xe0, 0xd6, 0xe9, 0xf9, 0x0f, 0xe8, 0x4a, 0x25, 0x7d, 0x83, 0x12, 0xb0, 0x4c, 0x93, 0xfe, 0x61, 0xc1, 0xed, 0xd3, 0xf3, 0x1f, 0xd0, 0x95, 0x4a, 0xfa, 0x06,
0x42, 0xf0, 0x11, 0x7e, 0x20, 0xd4, 0x03, 0xa8, 0x27, 0x69, 0x3e, 0x83, 0x2c, 0xe1, 0x02, 0x50, 0x85, 0xe0, 0x23, 0xfc, 0x40, 0xa8, 0xfb, 0x50, 0x4f, 0xd2, 0x7c, 0x06, 0x59, 0xc2, 0x05, 0xa0,
0x76, 0x09, 0xc6, 0xc1, 0x6c, 0xe0, 0xe9, 0x52, 0xd6, 0x59, 0x76, 0x54, 0x92, 0x98, 0xcf, 0x82, 0xec, 0x12, 0x8c, 0x83, 0xd9, 0xc0, 0xd3, 0xa5, 0xac, 0xb3, 0xec, 0xa8, 0x24, 0x31, 0x9f, 0x05,
0x88, 0x7b, 0xad, 0x75, 0xdd, 0xb7, 0xec, 0x48, 0xda, 0xb0, 0x1d, 0xe9, 0x00, 0x06, 0x5e, 0x6b, 0x11, 0xf7, 0x5a, 0xeb, 0xba, 0x6f, 0xd9, 0x91, 0xb4, 0x61, 0x2b, 0xd2, 0x01, 0x0c, 0xbc, 0xd6,
0x43, 0x1b, 0xe5, 0x67, 0x8a, 0xe0, 0x0c, 0x95, 0xe3, 0xb3, 0xa9, 0x18, 0x67, 0x65, 0x7c, 0x5a, 0x2d, 0x6d, 0x94, 0x9f, 0x29, 0x82, 0x33, 0x54, 0x8e, 0xcf, 0xa6, 0x62, 0x9c, 0x95, 0xf1, 0x69,
0x30, 0xa9, 0xd8, 0x76, 0x7a, 0xf7, 0x4a, 0x69, 0xa6, 0xda, 0xa9, 0xb8, 0x70, 0xd1, 0x01, 0xe8, 0xc1, 0xa4, 0x62, 0xdb, 0xee, 0xdd, 0x2f, 0xa5, 0x99, 0x6a, 0xa7, 0xe2, 0xc2, 0x45, 0x07, 0xa0,
0x27, 0xe8, 0x61, 0x28, 0x7d, 0x1e, 0xe8, 0xa8, 0x1b, 0xac, 0x84, 0xd0, 0xdb, 0x70, 0xab, 0xe4, 0x9f, 0xa0, 0x87, 0xa1, 0xf4, 0x79, 0xa0, 0xa3, 0x6e, 0xb0, 0x12, 0x42, 0xef, 0xc0, 0xed, 0x92,
0x26, 0x2d, 0x27, 0xa5, 0xb9, 0xef, 0x20, 0xc8, 0x7c, 0x2f, 0x74, 0x9e, 0xbe, 0xca, 0x0d, 0x95, 0x9b, 0xb4, 0x9c, 0x94, 0xe6, 0xbe, 0x83, 0x20, 0xf3, 0xbd, 0xd0, 0x79, 0xfa, 0x2a, 0x37, 0x54,
0x8e, 0xe9, 0xc3, 0xff, 0x0f, 0x90, 0xfe, 0x62, 0x43, 0xa3, 0x2c, 0x21, 0x2f, 0x60, 0x47, 0xdb, 0x3a, 0xa6, 0x0f, 0xff, 0x3f, 0x40, 0xfa, 0x8b, 0x0d, 0x8d, 0xb2, 0x84, 0xbc, 0x80, 0x6d, 0x6d,
0xa8, 0xb6, 0x61, 0x62, 0x78, 0x1e, 0x94, 0x78, 0x18, 0xbf, 0x1c, 0x16, 0x0a, 0xdf, 0xf9, 0x72, 0xa3, 0xda, 0x86, 0x89, 0xe1, 0x79, 0x58, 0xe2, 0x61, 0xfc, 0x72, 0x58, 0x28, 0x7c, 0xe7, 0xcb,
0x3c, 0xf0, 0x58, 0xd9, 0x46, 0x25, 0xcd, 0xdd, 0xc0, 0x10, 0x66, 0x49, 0x17, 0x08, 0xa1, 0xd0, 0xf1, 0xc0, 0x63, 0x65, 0x1b, 0x95, 0x34, 0x77, 0x03, 0x43, 0x98, 0x25, 0x5d, 0x20, 0x84, 0x42,
0x28, 0x4e, 0x79, 0xc3, 0xe6, 0x30, 0xd2, 0x83, 0x7d, 0x4d, 0x39, 0x44, 0x29, 0xfd, 0x70, 0x24, 0xa3, 0x38, 0xe5, 0x0d, 0x9b, 0xc3, 0x48, 0x0f, 0xf6, 0x34, 0xe5, 0x10, 0xa5, 0xf4, 0xc3, 0x91,
0xce, 0xe6, 0x5a, 0x58, 0x29, 0x23, 0x9f, 0xc1, 0xdd, 0x2a, 0x3c, 0xef, 0xee, 0x0a, 0x29, 0xfd, 0x38, 0x9b, 0x6b, 0x61, 0xa5, 0x8c, 0x7c, 0x06, 0xf7, 0xaa, 0xf0, 0xbc, 0xbb, 0x2b, 0xa4, 0xf4,
0xd3, 0x82, 0x9d, 0x52, 0x4a, 0xea, 0x5e, 0xf8, 0xba, 0x41, 0x72, 0x66, 0x9e, 0x7a, 0x7e, 0x56, 0x6f, 0x0b, 0xb6, 0x4b, 0x29, 0xa9, 0x7b, 0xe1, 0xeb, 0x06, 0xc9, 0x99, 0x79, 0xea, 0xf9, 0x59,
0xb7, 0x50, 0xfa, 0x13, 0x14, 0x92, 0x4f, 0x62, 0x9d, 0xda, 0x1a, 0x2b, 0x00, 0x25, 0xd5, 0x3e, 0xdd, 0x42, 0xe9, 0x4f, 0x50, 0x48, 0x3e, 0x89, 0x75, 0x6a, 0x6b, 0xac, 0x00, 0x94, 0x54, 0xfb,
0xbe, 0x9d, 0xc5, 0x68, 0xd2, 0x2a, 0x00, 0xf2, 0x09, 0x34, 0xd5, 0xa5, 0xf4, 0x5d, 0x2e, 0xfd, 0xf8, 0x76, 0x16, 0xa3, 0x49, 0xab, 0x00, 0xc8, 0x27, 0xd0, 0x54, 0x97, 0xd2, 0x77, 0xb9, 0xf4,
0x28, 0xfc, 0x1a, 0x67, 0x3a, 0x9b, 0x75, 0xb6, 0x80, 0xaa, 0x57, 0x2d, 0x10, 0xd3, 0xa8, 0x1b, 0xa3, 0xf0, 0x6b, 0x9c, 0xe9, 0x6c, 0xd6, 0xd9, 0x02, 0xaa, 0x5e, 0xb5, 0x40, 0x4c, 0xa3, 0x6e,
0x4c, 0x7f, 0xd3, 0x33, 0x68, 0xce, 0x17, 0x9e, 0x74, 0x97, 0x1b, 0xd5, 0x98, 0xef, 0x83, 0x8a, 0x30, 0xfd, 0x4d, 0x0e, 0x81, 0x94, 0x4a, 0x9c, 0x55, 0x63, 0x43, 0x6b, 0x54, 0x48, 0xe8, 0x19,
0xc6, 0x1f, 0x85, 0x5c, 0x4e, 0x13, 0x34, 0x6d, 0x28, 0x00, 0x7a, 0x0c, 0xfb, 0x55, 0xad, 0xd4, 0x34, 0xe7, 0x1b, 0x45, 0xba, 0xcb, 0x8d, 0x6d, 0xcc, 0xf7, 0x4d, 0x45, 0xef, 0x8f, 0x42, 0x2e,
0xef, 0x8c, 0x5f, 0xce, 0xb1, 0x16, 0x80, 0xb9, 0x87, 0x76, 0x7e, 0x0f, 0x7f, 0xb7, 0x60, 0x7f, 0xa7, 0x09, 0x9a, 0xb6, 0x15, 0x00, 0x3d, 0x86, 0xbd, 0xaa, 0xd6, 0xeb, 0x77, 0xc9, 0x2f, 0xe7,
0x58, 0x2e, 0x6b, 0x3f, 0x0a, 0xa5, 0x1a, 0x55, 0x5f, 0x42, 0x23, 0x7d, 0x4c, 0xc7, 0x18, 0xa0, 0x58, 0x0b, 0xc0, 0xdc, 0x5b, 0x3b, 0xbf, 0xb7, 0xbf, 0x5b, 0xb0, 0x37, 0x2c, 0xb7, 0xa1, 0x1f,
0xc4, 0x8a, 0x0b, 0x79, 0x5a, 0x12, 0xbf, 0xae, 0xb1, 0x39, 0x75, 0xf2, 0xdc, 0x64, 0x67, 0xac, 0x85, 0x52, 0x8d, 0xb6, 0x2f, 0xa1, 0x91, 0x3e, 0xbe, 0x63, 0x0c, 0x50, 0x62, 0xc5, 0x05, 0x3e,
0x6d, 0x6d, 0x7d, 0x77, 0xf1, 0x3a, 0xe7, 0xc6, 0x65, 0xe5, 0x97, 0x5b, 0xb0, 0xf1, 0x33, 0x0f, 0x2d, 0x89, 0x5f, 0xd7, 0xd8, 0x9c, 0x3a, 0x79, 0x6e, 0xb2, 0x33, 0xd6, 0xb6, 0xb6, 0xbe, 0xb7,
0xa6, 0x48, 0x3b, 0xd0, 0x28, 0x3b, 0x59, 0x7a, 0x44, 0x47, 0xa6, 0xef, 0x46, 0xfc, 0x31, 0xec, 0x78, 0xfd, 0x73, 0xe3, 0xb2, 0xf2, 0xcb, 0x4d, 0xb8, 0xf5, 0x33, 0x0f, 0xa6, 0x48, 0x3b, 0xd0,
0x7a, 0xfa, 0x2b, 0x39, 0x43, 0x4c, 0xf2, 0x09, 0x34, 0x0f, 0xd2, 0x77, 0x70, 0x67, 0x2e, 0xe1, 0x28, 0x3b, 0x59, 0x7a, 0x74, 0x47, 0xe6, 0x9e, 0x18, 0xf1, 0xc7, 0xb0, 0xe3, 0xe9, 0xaf, 0xe4,
0x61, 0xc8, 0x63, 0x31, 0x8e, 0xa4, 0xba, 0xf6, 0xa9, 0xa6, 0x37, 0xf0, 0xd2, 0x41, 0x58, 0x67, 0x0c, 0x31, 0xc9, 0x27, 0xd6, 0x3c, 0x48, 0xdf, 0xc1, 0xdd, 0xb9, 0x84, 0x87, 0x21, 0x8f, 0xc5,
0x25, 0x64, 0x99, 0xde, 0xae, 0xa2, 0xff, 0xd5, 0x82, 0x46, 0x46, 0x7d, 0xcc, 0x25, 0x27, 0xcf, 0x38, 0x92, 0xea, 0x99, 0xa4, 0x9a, 0xde, 0xc0, 0x4b, 0x07, 0x67, 0x9d, 0x95, 0x90, 0x65, 0x7a,
0x60, 0xcb, 0x4d, 0x6b, 0x6a, 0x86, 0xeb, 0x83, 0xc5, 0x2a, 0x2c, 0x94, 0x9e, 0x65, 0xfa, 0x6a, 0xbb, 0x8a, 0xfe, 0x57, 0x0b, 0x1a, 0x19, 0xf5, 0x31, 0x97, 0x9c, 0x3c, 0x83, 0x4d, 0x37, 0xad,
0x37, 0x09, 0x13, 0x9d, 0xa9, 0x60, 0x77, 0x95, 0x6d, 0x96, 0x05, 0xcb, 0x2d, 0xe8, 0x8f, 0x66, 0xa9, 0x19, 0xc6, 0x0f, 0x17, 0xab, 0xb0, 0x50, 0x7a, 0x96, 0xe9, 0xab, 0x5d, 0x26, 0x4c, 0x74,
0xc4, 0x0c, 0xa7, 0xe7, 0xc2, 0x4d, 0xfc, 0x58, 0x5d, 0x4f, 0xf5, 0x36, 0xcc, 0x40, 0xce, 0x52, 0xa6, 0x82, 0xdd, 0x55, 0xb6, 0x59, 0x16, 0x2c, 0xb7, 0xa0, 0x3f, 0x9a, 0x91, 0x34, 0x9c, 0x9e,
0xcc, 0xcf, 0xe4, 0x39, 0x6c, 0x72, 0x57, 0x69, 0x69, 0x67, 0xcd, 0x1e, 0x5d, 0x72, 0x56, 0x62, 0x0b, 0x37, 0xf1, 0x63, 0x75, 0x9d, 0xd5, 0x5b, 0x32, 0x03, 0x3c, 0x4b, 0x31, 0x3f, 0x93, 0xe7,
0x7a, 0xa1, 0x35, 0x99, 0xb1, 0x78, 0x78, 0x09, 0xdb, 0x27, 0x49, 0xd2, 0x8f, 0x3c, 0x14, 0xa4, 0xb0, 0xc1, 0x5d, 0xa5, 0xa5, 0x9d, 0x35, 0x7b, 0x74, 0xc9, 0x59, 0x89, 0xe9, 0x85, 0xd6, 0x64,
0x09, 0xf0, 0x36, 0xc4, 0xab, 0x18, 0x5d, 0x89, 0x9e, 0x53, 0x23, 0x8e, 0x19, 0x51, 0x6f, 0x7c, 0xc6, 0xe2, 0xd1, 0x25, 0x6c, 0x9d, 0x24, 0x49, 0x3f, 0xf2, 0x50, 0x90, 0x26, 0xc0, 0xdb, 0x10,
0x21, 0xfc, 0x70, 0xe4, 0x58, 0x64, 0xcf, 0x34, 0xee, 0xe4, 0xca, 0x17, 0x52, 0x38, 0x36, 0xb9, 0xaf, 0x62, 0x74, 0x25, 0x7a, 0x4e, 0x8d, 0x38, 0x66, 0xa4, 0xbd, 0xf1, 0x85, 0xf0, 0xc3, 0x91,
0x0d, 0x7b, 0x1a, 0xf8, 0x26, 0x92, 0x83, 0xb0, 0xcf, 0xdd, 0x31, 0x3a, 0x6b, 0x84, 0x40, 0x53, 0x63, 0x91, 0x5d, 0xd3, 0xb8, 0x93, 0x2b, 0x5f, 0x48, 0xe1, 0xd8, 0xe4, 0x0e, 0xec, 0x6a, 0xe0,
0x83, 0x03, 0x91, 0x36, 0xd8, 0x73, 0xd6, 0x95, 0xe5, 0x49, 0x92, 0x44, 0xc9, 0xe9, 0xc5, 0x85, 0x9b, 0x48, 0x0e, 0xc2, 0x3e, 0x77, 0xc7, 0xe8, 0xac, 0x11, 0x02, 0x4d, 0x0d, 0x0e, 0x44, 0xda,
0x40, 0xe9, 0x78, 0x0f, 0x9f, 0xc1, 0xbd, 0x15, 0xb1, 0x91, 0x5d, 0xa8, 0x1b, 0xf4, 0x1c, 0x9d, 0x60, 0xcf, 0x59, 0x57, 0x96, 0x27, 0x49, 0x12, 0x25, 0xa7, 0x17, 0x17, 0x02, 0xa5, 0xe3, 0x3d,
0x9a, 0x32, 0x7d, 0x1b, 0x8a, 0x1c, 0xb0, 0x7a, 0x7f, 0xd9, 0x50, 0x4f, 0x6d, 0x67, 0xa1, 0x4b, 0x7a, 0x06, 0xf7, 0x57, 0xc4, 0x46, 0x76, 0xa0, 0x6e, 0xd0, 0x73, 0x74, 0x6a, 0xca, 0xf4, 0x6d,
0xfa, 0xb0, 0x9d, 0xad, 0x3a, 0xd2, 0xae, 0xdc, 0x7f, 0x7a, 0x92, 0xb7, 0xef, 0x57, 0xef, 0xc6, 0x28, 0x72, 0xc0, 0xea, 0xfd, 0x69, 0x43, 0x3d, 0xb5, 0x9d, 0x85, 0x2e, 0xe9, 0xc3, 0x56, 0xb6,
0x74, 0x82, 0xbf, 0x32, 0x8c, 0x6a, 0x1f, 0x90, 0xfb, 0x4b, 0xd3, 0xbb, 0x58, 0x46, 0xed, 0x83, 0x1a, 0x49, 0xbb, 0x72, 0x5f, 0xea, 0xc9, 0xdf, 0x7e, 0x50, 0xbd, 0x4b, 0xd3, 0x89, 0xff, 0xca,
0x6a, 0xe1, 0x12, 0x4f, 0x10, 0x54, 0xf1, 0xe4, 0x8b, 0xa5, 0x8a, 0xa7, 0xb4, 0x51, 0x18, 0x38, 0x30, 0xaa, 0xfd, 0x41, 0x1e, 0x2c, 0x4d, 0xfb, 0x62, 0x79, 0xb5, 0xf7, 0xab, 0x85, 0x4b, 0x3c,
0xc5, 0x8e, 0x1e, 0xca, 0x04, 0xf9, 0x84, 0x1c, 0x2c, 0xbd, 0xe1, 0xd2, 0x02, 0x6f, 0x7f, 0x50, 0x41, 0x50, 0xc5, 0x93, 0x2f, 0xa2, 0x2a, 0x9e, 0xd2, 0x06, 0x62, 0xe0, 0x14, 0x3b, 0x7d, 0x28,
0x7a, 0x68, 0x3d, 0xb1, 0x5e, 0x7e, 0xfa, 0xf7, 0x75, 0xc7, 0x7a, 0x7f, 0xdd, 0xb1, 0xfe, 0xbd, 0x13, 0xe4, 0x13, 0xb2, 0xbf, 0xf4, 0x86, 0x4b, 0x0b, 0xbf, 0xfd, 0x41, 0xe9, 0x81, 0xf5, 0xc4,
0xee, 0x58, 0xbf, 0xdd, 0x74, 0x6a, 0xef, 0x6f, 0x3a, 0xb5, 0x7f, 0x6e, 0x3a, 0xb5, 0xef, 0xdb, 0x7a, 0xf9, 0xe9, 0x5f, 0xd7, 0x1d, 0xeb, 0xfd, 0x75, 0xc7, 0xfa, 0xf7, 0xba, 0x63, 0xfd, 0x76,
0xab, 0xff, 0xf5, 0x3b, 0xdf, 0xd4, 0x7f, 0x8e, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x96, 0xd3, 0xa9, 0xbd, 0xbf, 0xe9, 0xd4, 0xfe, 0xb9, 0xe9, 0xd4, 0xbe, 0x6f, 0xaf, 0xfe, 0x57, 0xf1,
0xb3, 0xaa, 0x1f, 0x0a, 0x00, 0x00, 0x7c, 0x43, 0xff, 0x39, 0xfa, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x13, 0xff, 0xe7, 0x17, 0x4f, 0x0a,
0x00, 0x00,
} }
func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) { func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) {
@ -1784,6 +1793,13 @@ func (m *SpaceHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.SpaceHeaderPayload) > 0 {
i -= len(m.SpaceHeaderPayload)
copy(dAtA[i:], m.SpaceHeaderPayload)
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.SpaceHeaderPayload)))
i--
dAtA[i] = 0x32
}
if len(m.Seed) > 0 { if len(m.Seed) > 0 {
i -= len(m.Seed) i -= len(m.Seed)
copy(dAtA[i:], m.Seed) copy(dAtA[i:], m.Seed)
@ -2387,6 +2403,10 @@ func (m *SpaceHeader) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovSpacesync(uint64(l)) n += 1 + l + sovSpacesync(uint64(l))
} }
l = len(m.SpaceHeaderPayload)
if l > 0 {
n += 1 + l + sovSpacesync(uint64(l))
}
return n return n
} }
@ -4041,6 +4061,40 @@ func (m *SpaceHeader) Unmarshal(dAtA []byte) error {
m.Seed = []byte{} m.Seed = []byte{}
} }
iNdEx = postIndex iNdEx = postIndex
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SpaceHeaderPayload", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SpaceHeaderPayload = append(m.SpaceHeaderPayload[:0], dAtA[iNdEx:postIndex]...)
if m.SpaceHeaderPayload == nil {
m.SpaceHeaderPayload = []byte{}
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipSpacesync(dAtA[iNdEx:]) skippy, err := skipSpacesync(dAtA[iNdEx:])

View File

@ -38,11 +38,12 @@ func (m *MockCoordinatorClient) EXPECT() *MockCoordinatorClientMockRecorder {
} }
// ChangeStatus mocks base method. // ChangeStatus mocks base method.
func (m *MockCoordinatorClient) ChangeStatus(arg0 context.Context, arg1 string, arg2 *treechangeproto.RawTreeChangeWithId) error { func (m *MockCoordinatorClient) ChangeStatus(arg0 context.Context, arg1 string, arg2 *treechangeproto.RawTreeChangeWithId) (*coordinatorproto.SpaceStatusPayload, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChangeStatus", arg0, arg1, arg2) ret := m.ctrl.Call(m, "ChangeStatus", arg0, arg1, arg2)
ret0, _ := ret[0].(error) ret0, _ := ret[0].(*coordinatorproto.SpaceStatusPayload)
return ret0 ret1, _ := ret[1].(error)
return ret0, ret1
} }
// ChangeStatus indicates an expected call of ChangeStatus. // ChangeStatus indicates an expected call of ChangeStatus.
@ -110,10 +111,10 @@ func (mr *MockCoordinatorClientMockRecorder) SpaceSign(arg0, arg1, arg2 interfac
} }
// StatusCheck mocks base method. // StatusCheck mocks base method.
func (m *MockCoordinatorClient) StatusCheck(arg0 context.Context, arg1 string) (*coordinatorproto.SpaceStatusCheckResponse, error) { func (m *MockCoordinatorClient) StatusCheck(arg0 context.Context, arg1 string) (*coordinatorproto.SpaceStatusPayload, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StatusCheck", arg0, arg1) ret := m.ctrl.Call(m, "StatusCheck", arg0, arg1)
ret0, _ := ret[0].(*coordinatorproto.SpaceStatusCheckResponse) ret0, _ := ret[0].(*coordinatorproto.SpaceStatusPayload)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }

View File

@ -25,11 +25,13 @@ type Peer interface {
Id() string Id() string
LastUsage() time.Time LastUsage() time.Time
UpdateLastUsage() UpdateLastUsage()
TryClose(objectTTL time.Duration) (res bool, err error)
drpc.Conn drpc.Conn
} }
type peer struct { type peer struct {
id string id string
ttl time.Duration
lastUsage int64 lastUsage int64
sc sec.SecureConn sc sec.SecureConn
drpc.Conn drpc.Conn
@ -76,6 +78,13 @@ func (p *peer) UpdateLastUsage() {
atomic.StoreInt64(&p.lastUsage, time.Now().Unix()) atomic.StoreInt64(&p.lastUsage, time.Now().Unix())
} }
func (p *peer) TryClose(objectTTL time.Duration) (res bool, err error) {
if time.Now().Sub(p.LastUsage()) < objectTTL {
return false, nil
}
return true, p.Close()
}
func (p *peer) Close() (err error) { func (p *peer) Close() (err error) {
log.Debug("peer close", zap.String("peerId", p.id)) log.Debug("peer close", zap.String("peerId", p.id))
return p.Conn.Close() return p.Conn.Close()

View File

@ -49,7 +49,7 @@ func (p *pool) Get(ctx context.Context, id string) (peer.Peer, error) {
default: default:
return pr, nil return pr, nil
} }
_, _ = p.cache.Remove(id) _, _ = p.cache.Remove(ctx, id)
return p.Get(ctx, id) return p.Get(ctx, id)
} }

View File

@ -194,6 +194,10 @@ func (t *testPeer) LastUsage() time.Time {
func (t *testPeer) UpdateLastUsage() {} func (t *testPeer) UpdateLastUsage() {}
func (t *testPeer) TryClose(objectTTL time.Duration) (res bool, err error) {
return true, t.Close()
}
func (t *testPeer) Close() error { func (t *testPeer) Close() error {
select { select {
case <-t.closed: case <-t.closed:

View File

@ -103,6 +103,10 @@ type testPeer struct {
drpc.Conn drpc.Conn
} }
func (t testPeer) TryClose(objectTTL time.Duration) (res bool, err error) {
return true, t.Close()
}
func (t testPeer) Id() string { func (t testPeer) Id() string {
return t.id return t.id
} }