v2ray-core/common/environment/deferredpersistentstorage/defereredPersistentStorage.go
Xiaokang Wang (Shelikhoo) 78cd513b82
Add Persistent Storage Support to V2Ray (#3300)
* update protogen to strip unused part

* add persistent storage support

* fix coding style

* update linter setting

* update github integration
2025-02-05 20:36:40 +00:00

112 lines
2.7 KiB
Go

package deferredpersistentstorage
import (
"context"
"github.com/v2fly/v2ray-core/v5/app/persistentstorage"
"github.com/v2fly/v2ray-core/v5/common/errors"
"github.com/v2fly/v2ray-core/v5/features/extension/storage"
)
type DeferredPersistentStorage interface {
storage.ScopedPersistentStorage
ProvideInner(ctx context.Context, inner persistentstorage.ScopedPersistentStorage)
}
var errNotExist = errors.New("persistent storage does not exist")
type deferredPersistentStorage struct {
ready context.Context
done context.CancelFunc
inner persistentstorage.ScopedPersistentStorage
awaitingChildren []*deferredPersistentStorage
intoScopes []string
}
func (d *deferredPersistentStorage) ScopedPersistentStorageEngine() {
}
func (d *deferredPersistentStorage) Put(ctx context.Context, key []byte, value []byte) error {
<-d.ready.Done()
if d.inner == nil {
return errNotExist
}
return d.inner.Put(ctx, key, value)
}
func (d *deferredPersistentStorage) Get(ctx context.Context, key []byte) ([]byte, error) {
<-d.ready.Done()
if d.inner == nil {
return nil, errNotExist
}
return d.inner.Get(ctx, key)
}
func (d *deferredPersistentStorage) List(ctx context.Context, keyPrefix []byte) ([][]byte, error) {
<-d.ready.Done()
if d.inner == nil {
return nil, errNotExist
}
return d.inner.List(ctx, keyPrefix)
}
func (d *deferredPersistentStorage) Clear(ctx context.Context) {
<-d.ready.Done()
if d.inner == nil {
return
}
d.inner.Clear(ctx)
}
func (d *deferredPersistentStorage) NarrowScope(ctx context.Context, key []byte) (storage.ScopedPersistentStorage, error) {
if d.ready.Err() != nil {
return d.inner.NarrowScope(ctx, key)
}
ready, done := context.WithCancel(ctx)
swallowCopyScopes := d.intoScopes
dps := &deferredPersistentStorage{
ready: ready,
done: done,
inner: nil,
intoScopes: append(swallowCopyScopes, string(key)),
}
d.awaitingChildren = append(d.awaitingChildren, dps)
return dps, nil
}
func (d *deferredPersistentStorage) DropScope(ctx context.Context, key []byte) error {
<-d.ready.Done()
if d.inner == nil {
return errNotExist
}
return d.inner.DropScope(ctx, key)
}
func (d *deferredPersistentStorage) ProvideInner(ctx context.Context, inner persistentstorage.ScopedPersistentStorage) {
d.inner = inner
if inner != nil {
for _, scope := range d.intoScopes {
newScope, err := inner.NarrowScope(ctx, []byte(scope))
if err != nil {
panic(err)
}
d.inner = newScope
}
}
for _, child := range d.awaitingChildren {
child.ProvideInner(ctx, d.inner)
}
d.done()
}
func NewDeferredPersistentStorage(ctx context.Context) DeferredPersistentStorage {
ready, done := context.WithCancel(ctx)
return &deferredPersistentStorage{
ready: ready,
done: done,
inner: nil,
}
}