Some checks failed
Coverage / coverage (push) Failing after 6s
Tests / test (1.24.x, ubuntu-latest) (push) Failing after 42s
Tests / test (1.26.x, ubuntu-latest) (push) Failing after 38s
Tests / test (1.25.x, ubuntu-latest) (push) Failing after 35s
Tests / test (1.25.x, windows-latest) (push) Has been cancelled
Tests / test (1.26.x, macos-latest) (push) Has been cancelled
Tests / test (1.26.x, windows-latest) (push) Has been cancelled
Tests / test (1.24.x, macos-latest) (push) Has been cancelled
Tests / test (1.24.x, windows-latest) (push) Has been cancelled
Tests / test (1.25.x, macos-latest) (push) Has been cancelled
130 lines
3.7 KiB
Go
130 lines
3.7 KiB
Go
// Copyright (c) 2026 Couchbase, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package util
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
index "github.com/blevesearch/bleve_index_api"
|
|
)
|
|
|
|
// This file provides a mechanism for users of bleve to provide callbacks
|
|
// that can process data before it is written to disk, and after it is read
|
|
// from disk. This can be used for things like encryption, compression, etc.
|
|
|
|
// The user is responsible for ensuring that the writer and reader callbacks
|
|
// are compatible with each other, and that any state needed by the callbacks
|
|
// is managed appropriately. For example, if the writer callback uses a
|
|
// unique key or nonce per write, the reader callback must be able to
|
|
// determine the correct key or nonce to use for each read.
|
|
|
|
// The callbacks are identified by an id string, which is returned by the
|
|
// WriterHook. The same id string is passed to the ReaderHook when creating a reader.
|
|
// This allows the reader to determine which callback to use for a given file.
|
|
|
|
// Support for identifying all callbacks used by a given index and to remove
|
|
// selected callbacks associated with ids is provided via index.WriterIdsInUse()
|
|
// and index.DropWriterIds().
|
|
|
|
const DefaultFileCallbackId = ""
|
|
|
|
// FileWriter and FileReader interfaces are wrappers around the callback functions
|
|
// provided by the user. They provide a convenient way to apply the callbacks to data
|
|
// being written to or read from a file. They also store the id the callbacks,
|
|
// which can be useful for managing state across multiple reads and writes.
|
|
type FileWriter interface {
|
|
Process(data []byte) []byte
|
|
Id() string
|
|
}
|
|
type fileWriterImpl struct {
|
|
id string
|
|
processor func(data []byte) []byte
|
|
}
|
|
|
|
func NewFileWriter(context []byte) (FileWriter, error) {
|
|
rv := &fileWriterImpl{}
|
|
|
|
if index.WriterHook != nil {
|
|
var err error
|
|
rv.id, rv.processor, err = index.WriterHook(context)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return rv, nil
|
|
}
|
|
|
|
func (w *fileWriterImpl) Process(data []byte) []byte {
|
|
if w.processor != nil {
|
|
return w.processor(data)
|
|
}
|
|
return data
|
|
}
|
|
|
|
func (w *fileWriterImpl) Id() string {
|
|
return w.id
|
|
}
|
|
|
|
type FileReader interface {
|
|
Process(data []byte) ([]byte, error)
|
|
Id() string
|
|
}
|
|
|
|
type fileReaderImpl struct {
|
|
id string
|
|
processor func(data []byte) ([]byte, error)
|
|
}
|
|
|
|
func NewFileReader(id string, context []byte) (FileReader, error) {
|
|
rv := &fileReaderImpl{
|
|
id: id,
|
|
}
|
|
|
|
if index.ReaderHook != nil {
|
|
var err error
|
|
rv.processor, err = index.ReaderHook(id, context)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else if id != "" {
|
|
return nil, fmt.Errorf("reader callback id %s provided but no ReaderHook is set", id)
|
|
}
|
|
|
|
return rv, nil
|
|
}
|
|
|
|
func (r *fileReaderImpl) Process(data []byte) ([]byte, error) {
|
|
if r.processor != nil {
|
|
return r.processor(data)
|
|
}
|
|
return data, nil
|
|
}
|
|
|
|
func (r *fileReaderImpl) Id() string {
|
|
return r.id
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// set of bolt keys and bucket names that require processing by the reader
|
|
// and writer callbacks.
|
|
var boltKeysProcessed = map[string]struct{}{
|
|
string(BoltDeletedKey): {},
|
|
string(BoltInternalKey): {},
|
|
string(BoltStatsKey): {},
|
|
string(BoltUpdatedFieldsKey): {},
|
|
}
|