func (bucket *WalrusBucket) waitAfterWrite(seq uint64, opt sgbucket.WriteOptions) error {
	if opt&sgbucket.Persist != 0 {
		if bucket.path == "" {
			return errors.New("Bucket is non-persistent")
		}
		start := time.Now()
		for {
			time.Sleep(100 * time.Millisecond)
			if bucket.isSequenceSaved(seq) {
				break
			} else if time.Since(start) > 5*time.Second {
				return sgbucket.ErrTimeout
			}
		}
	}
	return nil
}
Waits until the given sequence has been persisted or made indexable.
package walrus
import (
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"os"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
	sgbucket "github.com/couchbase/sg-bucket"
	"github.com/google/uuid"
)
const (
	SimulatedVBucketCount = 1024  
)
var MaxDocSize = 0  
type DocTooBigErr struct{}
func (err DocTooBigErr) Error() string {
	return "Document value was too large!"
}
type walrusData struct {
	LastSeq    uint64                          
	Docs       map[string]*walrusDoc           
	DesignDocs map[string]*sgbucket.DesignDoc  
}
type WalrusBucket struct {
	name         string                      
	uuid         string                      
	path         string                      
	saving       bool                        
	lastSeqSaved uint64                      
	lock         sync.RWMutex                
	views        map[string]walrusDesignDoc  
	vbSeqs       sgbucket.VbucketSeqCounter  
	tapFeeds     []*tapFeedImpl
	walrusData
}
type walrusDoc struct {
	Raw      []byte  
	IsJSON   bool    
	VbNo     uint32  
	VbSeq    uint64  
	Sequence uint64  
}
func NewBucket(bucketName string) *WalrusBucket {
	logg("NewBucket %s", bucketName)
	bucket := &WalrusBucket{
		name: bucketName,
		uuid: uuid.New().String(),
		walrusData: walrusData{
			Docs:       map[string]*walrusDoc{},
			DesignDocs: map[string]*sgbucket.DesignDoc{},
		},
		vbSeqs: sgbucket.NewMapVbucketSeqCounter(SimulatedVBucketCount),
		views:  map[string]walrusDesignDoc{},
	}
	runtime.SetFinalizer(bucket, (*WalrusBucket).Close)
	return bucket
}
var buckets map[[3]string]*WalrusBucket
var bucketsLock sync.Mutex
func GetBucket(url, poolName, bucketName string) (*WalrusBucket, error) {
	bucketsLock.Lock()
	defer bucketsLock.Unlock()
	if buckets == nil {
		buckets = make(map[[3]string]*WalrusBucket)
	}
	key := [3]string{url, poolName, bucketName}
	bucket := buckets[key]
	if bucket == nil {
		dir := bucketURLToDir(url)
		if dir == "" {
			bucket = NewBucket(bucketName)
		} else {
			var err error
			bucket, err = NewPersistentBucket(dir, poolName, bucketName)
			if err != nil {
				return nil, err
			}
		}
		buckets[key] = bucket
	}
	return bucket, nil
}
func bucketURLToDir(urlStr string) (dir string) {
	if urlStr != "" {
		if strings.HasPrefix(urlStr, "/") || strings.HasPrefix(urlStr, ".") {
			return urlStr
		}
		urlobj, _ := url.Parse(urlStr)
		if urlobj != nil && (urlobj.Scheme == "walrus" || urlobj.Scheme == "file") {
			dir = urlobj.Path
			if dir == "" {
				dir = urlobj.Opaque
			} else if strings.HasPrefix(dir, "//") {
				dir = dir[2:]
			}
			if dir == "/" {
				dir = ""
			}
		}
	}
	return
}
func (bucket *WalrusBucket) VBHash(docID string) uint32 {
	return 0
}
func (bucket *WalrusBucket) _nextSequence() uint64 {
	bucket._saveSoon()
	bucket.LastSeq++
	return bucket.LastSeq
}
func (bucket *WalrusBucket) GetName() string {
	return bucket.name  
}
func (bucket *WalrusBucket) Close() {
	bucketsLock.Lock()
	defer bucketsLock.Unlock()
	for key, value := range buckets {
		if value == bucket {
			delete(buckets, key)
			break
		}
	}
	bucket.lock.Lock()
	defer bucket.lock.Unlock()
	if bucket.Docs != nil {
		logg("Close %s", bucket.GetName())
		bucket._closePersist()
		bucket.Docs = nil
		bucket.DesignDocs = nil
		bucket.views = nil
	}
}
func (bucket *WalrusBucket) CloseAndDelete() error {
	path := bucket.path
	bucket.Close()
	if path == "" {
		return nil
	}
	return os.Remove(path)
}
func (bucket *WalrusBucket) assertNotClosed() {
	if bucket.Docs == nil {
		panic(fmt.Sprintf("Accessing closed Walrus bucket %q", bucket.name))
	}
}
func (bucket *WalrusBucket) missingError(key string) error {
	bucket.assertNotClosed()
	return sgbucket.MissingError{key}
}
func copySlice(slice []byte) []byte {
	if slice == nil {
		return nil
	}
	copied := make([]byte, len(slice))
	copy(copied, slice)
	return copied
}
func (bucket *WalrusBucket) getRaw(k string) ([]byte, uint64, error) {
	bucket.lock.RLock()
	defer bucket.lock.RUnlock()
	doc := bucket.Docs[k]
	if doc == nil || doc.Raw == nil {
		return nil, 0, bucket.missingError(k)
	}
	return copySlice(doc.Raw), doc.Sequence, nil
}
func (bucket *WalrusBucket) GetRaw(k string) (rv []byte, cas uint64, err error) {
	raw, cas, err := bucket.getRaw(k)
	return copySlice(raw), cas, err  
}
func (bucket *WalrusBucket) GetAndTouchRaw(k string, exp uint32) (rv []byte, cas uint64, err error) {
	return bucket.GetRaw(k)
}
func (bucket *WalrusBucket) Touch(k string, exp uint32) (casOut uint64, err error) {
	_, casOut, err = bucket.getRaw(k)
	return casOut, err
}
func (bucket *WalrusBucket) Get(k string, rv interface{}) (cas uint64, err error) {
	raw, cas, err := bucket.getRaw(k)
	if err != nil {
		return 0, err
	}
	switch typedRV := rv.(type) {
	case *[]byte:
		*typedRV = copySlice(raw)
		return cas, nil
	default:
		return cas, json.Unmarshal(raw, rv)
	}
}
func (bucket *WalrusBucket) GetBulkRaw(keys []string) (map[string][]byte, error) {
	result := make(map[string][]byte)
	errs := multiError{}
	hadError := false
	for _, key := range keys {
		value, _, err := bucket.GetRaw(key)
		if err != nil {
			errs = append(errs, err)
		} else {
			result[key] = value
		}
	}
	if hadError {
		return result, errs
	} else {
		return result, nil
	}
}
func (bucket *WalrusBucket) Write(k string, flags int, exp uint32, v interface{}, opt sgbucket.WriteOptions) (err error) {
	isJSON := (opt&sgbucket.Raw == 0)
	data, err := bucket.getData(v, isJSON)
	if err != nil {
		return err
	}
	seq, err := bucket.write(k, exp, data, opt)
	if err != nil {
		return
	}
	return bucket.waitAfterWrite(seq, opt)
}
func (bucket *WalrusBucket) WriteCas(k string, flags int, exp uint32, cas uint64, v interface{}, opt sgbucket.WriteOptions) (casOut uint64, err error) {
	isJSON := (opt&sgbucket.Raw == 0)
	data, err := bucket.getData(v, isJSON)
	if err != nil {
		return 0, err
	}
	doc := &walrusDoc{}
	doc.Sequence = cas
	doc.Raw = data
	doc.IsJSON = isJSON
	casOut, err = bucket.updateDoc(k, doc)
	if err != nil {
		return 0, err
	}
	if casOut == 0 {
		return casOut, errors.New("CAS mismatch")
	}
	err = bucket.waitAfterWrite(casOut, opt)
	return casOut, err
}
func (bucket *WalrusBucket) Remove(k string, cas uint64) (casOut uint64, err error) {
	doc := &walrusDoc{}
	doc.Sequence = cas
	doc.Raw = nil
	doc.IsJSON = false
	casOut, err = bucket.updateDoc(k, doc)
	if err != nil {
		return 0, err
	}
	if casOut == 0 {
		return casOut, errors.New("CAS mismatch")
	}
	return casOut, nil
}
func (bucket *WalrusBucket) SetBulk(entries []*sgbucket.BulkSetEntry) (err error) {
	for _, entry := range entries {
		casOut, err := bucket.WriteCas(
			entry.Key,
			0,  
			0,  
			entry.Cas,
			entry.Value,
			sgbucket.Raw,  
		)
		entry.Cas = casOut
		entry.Error = err
	}
	return nil
}
func (bucket *WalrusBucket) WriteCasWithXattr(k string, xattrKey string, exp uint32, cas uint64, v interface{}, xv interface{}) (casOut uint64, err error) {
	return 0, errors.New("WriteCasWithXattr not implemented for walrus")
}
func (bucket *WalrusBucket) WriteWithXattr(k string, xattrKey string, exp uint32, cas uint64, value []byte, xattrValue []byte, isDelete bool, deleteBody bool) (casOut uint64, err error) {
	return 0, errors.New("WriteWithXattr not implemented for walrus")
}
func (bucket *WalrusBucket) GetWithXattr(k string, xattrKey string, userXattrKey string, rv interface{}, xv interface{}, uxv interface{}) (cas uint64, err error) {
	return 0, errors.New("GetWithXattr not implemented for walrus")
}
func (bucket *WalrusBucket) DeleteWithXattr(k string, xattrKey string) error {
	return errors.New("DeleteWithXattr not implemented for walrus")
}
func (bucket *WalrusBucket) GetXattr(k string, xattrKey string, xv interface{}) (casOut uint64, err error) {
	return 0, errors.New("GetXattr not implemented for walrus")
}
func (bucket *WalrusBucket) WriteUpdateWithXattr(k string, xattrKey string, userXattrKey string, exp uint32, previous *sgbucket.BucketDocument, callback sgbucket.WriteUpdateWithXattrFunc) (casOut uint64, err error) {
	return 0, errors.New("WriteUpdateWithXattr not implemented for walrus")
}
func (bucket *WalrusBucket) SetXattr(k string, xattrKey string, xv []byte) (casOut uint64, err error) {
	return 0, errors.New("SetXattr not implemented for walrus")
}
func (bucket *WalrusBucket) RemoveXattr(k string, xattrKey string, cas uint64) error {
	return  errors.New("RemoveXattr not implemented for walrus")
}
func (bucket *WalrusBucket) DeleteXattrs(k string, xattrKeys... string) error {
	return  errors.New("DeleteXattrs not implemented for walrus")
}
func (bucket *WalrusBucket) SubdocInsert(docID string, fieldPath string, cas uint64, value interface{}) error {
	return errors.New("SubdocInsert not implemented for walrus")
}
func (bucket *WalrusBucket) getData(v interface{}, isJSON bool) (data []byte, err error) {
	if !isJSON {
		if v != nil {
			data = copySlice(v.([]byte))
		}
		return data, nil
	}
	switch typedVal := v.(type) {
	case []byte:
		if typedVal != nil {
			data = copySlice(typedVal)
		}
	case *[]byte:
		if typedVal != nil {
			data = copySlice(*typedVal)
		}
	default:
		data, err = json.Marshal(v)
	}
	return data, err
}