mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
259 lines
11 KiB
Go
259 lines
11 KiB
Go
// Copyright 2017 Pilosa Corp.
|
|
//
|
|
// 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 pilosa
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/molecula/featurebase/v2/roaring"
|
|
txkey "github.com/molecula/featurebase/v2/short_txkey"
|
|
//txkey "github.com/molecula/featurebase/v2/txkey"
|
|
)
|
|
|
|
// writable initializes Tx that update, use !writable for read-only.
|
|
const writable = true
|
|
|
|
// Tx providers offer transactional storage for high-level roaring.Bitmaps and
|
|
// low-level roaring.Containers.
|
|
//
|
|
// The common 4-tuple of (index, field, view, shard) jointly specify a fragment.
|
|
// A fragment conceptually holds one roaring.Bitmap.
|
|
//
|
|
// Within the fragment, the ckey or container-key is the uint64 that specifies
|
|
// the high 48-bits of the roaring.Bitmap 64-bit space.
|
|
// The ckey is used to retreive a specific roaring.Container that
|
|
// is either a run, array, or raw-bitmap. The roaring.Container is the
|
|
// low 16-bits of the roaring.Bitmap space. Its size is at most
|
|
// 8KB (2^16 bits / (8 bits / byte) == 8192 bytes).
|
|
//
|
|
// The grain of the transaction is guaranteed to be at least at the shard
|
|
// within one index. Therefore updates to the any of the fields within
|
|
// the same shard will be atomically visible only once the transaction commits.
|
|
// Reads from another, concurrently open, transaction will not see updates
|
|
// that have not been committed.
|
|
type Tx interface {
|
|
|
|
// Type returns "roaring", "rbf", "bolt", "badger_roaring", or one of the other
|
|
// blue-green Tx types at the top of txfactory.go
|
|
Type() string
|
|
|
|
// Rollback must be called the end of read-only transactions. Either
|
|
// Rollback or Commit must be called at the end of writable transactions.
|
|
// It is safe to call Rollback multiple times, but it must be
|
|
// called at least once to release resources. Any Rollback after
|
|
// a Commit is ignored, so 'defer tx.Rollback()' should be commonly
|
|
// written after starting a new transaction.
|
|
//
|
|
// If there is an error during internal Rollback processing,
|
|
// this would be quite serious, and the underlying storage is
|
|
// expected to panic. Hence there is no explicit error returned
|
|
// from Rollback that needs to be checked.
|
|
Rollback()
|
|
|
|
// Commit makes the updates in the Tx visible to subsequent transactions.
|
|
Commit() error
|
|
|
|
// IsDone must return true if Rollback() or Commit() has already
|
|
// been called. Otherwise it must return false. This allows
|
|
// DBWrapper.CleanupTx(tx Tx) to be idempotent.
|
|
IsDone() bool
|
|
|
|
// Readonly returns the flag this transaction was created with
|
|
// during NewTx. If the transaction is writable, it will return false.
|
|
Readonly() bool
|
|
|
|
// UseRowCache is used by fragment.go unprotectedRow() to determine
|
|
// dynamically at runtime if RoaringTx
|
|
// are in use, which for continuity wants to continue to use the
|
|
// rowCache, or if other storage engines (RBF, Badger) are in
|
|
// use, which will mean that the bitmap data stored by the
|
|
// rowCache can disappear as it is un-mmap-ed, causing crashes.
|
|
UseRowCache() bool
|
|
|
|
// IncrementOpN updates internal statistics with the changedN provided.
|
|
IncrementOpN(index, field, view string, shard uint64, changedN int)
|
|
|
|
// Pointer gives us a memory address for the underlying
|
|
// transaction for debugging.
|
|
// It is public because we use it in roaring to report invalid
|
|
// container memory access outside of a transaction.
|
|
Pointer() string
|
|
|
|
// NewTxIterator returns it, a *roaring.Iterator whose it.Next() will
|
|
// successively return each uint64 stored in the conceptual roaring.Bitmap
|
|
// for the specified fragment.
|
|
NewTxIterator(index, field, view string, shard uint64) (it *roaring.Iterator)
|
|
|
|
// ContainerIterator loops over the containers in the conceptual
|
|
// roaring.Bitmap for the specified fragment.
|
|
// Calling Next() on the returned roaring.ContainerIterator gives
|
|
// you a roaring.Container that is either run, array, or raw bitmap.
|
|
// Return value 'found' is true when the ckey container was present.
|
|
// ckey of 0 gives all containers (in the fragment).
|
|
//
|
|
// ContainerIterator must not have side-effects. blueGreenTx will
|
|
// call it at the very beginning of commit to verify db contents.
|
|
//
|
|
// citer.Close() must be called when the client is done using it.
|
|
ContainerIterator(index, field, view string, shard uint64, ckey uint64) (citer roaring.ContainerIterator, found bool, err error)
|
|
|
|
// ApplyFilter applies a roaring.BitmapFilter to a specified shard,
|
|
// starting at the given container key. The filter's ConsiderData
|
|
// method may be called with transient Container objects which *must
|
|
// not* be retained or referenced after that function exits. Similarly,
|
|
// their data must not be retained. If you need the data later, you
|
|
// must copy it into some other memory.
|
|
ApplyFilter(index, field, view string, shard uint64, ckey uint64, filter roaring.BitmapFilter) (err error)
|
|
|
|
// RoaringBitmap retreives the roaring.Bitmap for the entire shard.
|
|
RoaringBitmap(index, field, view string, shard uint64) (*roaring.Bitmap, error)
|
|
|
|
// Container returns the roaring.Container for the given ckey
|
|
// (container-key or highbits), in the chosen fragment.
|
|
Container(index, field, view string, shard uint64, ckey uint64) (*roaring.Container, error)
|
|
|
|
// PutContainer stores c under the given ckey (container-key), in the specified fragment.
|
|
PutContainer(index, field, view string, shard uint64, ckey uint64, c *roaring.Container) error
|
|
|
|
// RemoveContainer deletes the roaring.Container under the given ckey (container-key),
|
|
// in the specified fragment.
|
|
RemoveContainer(index, field, view string, shard uint64, ckey uint64) error
|
|
|
|
Add(index, field, view string, shard uint64, a ...uint64) (changeCount int, err error)
|
|
|
|
// Remove removes the 'a' values from the Bitmap for the fragment.
|
|
Remove(index, field, view string, shard uint64, a ...uint64) (changeCount int, err error)
|
|
|
|
// Contains tests if the uint64 v is stored in the fragment's Bitmap.
|
|
Contains(index, field, view string, shard uint64, v uint64) (exists bool, err error)
|
|
|
|
// ForEach
|
|
ForEach(index, field, view string, shard uint64, fn func(i uint64) error) error
|
|
|
|
// ForEachRange
|
|
ForEachRange(index, field, view string, shard uint64, start, end uint64, fn func(uint64) error) error
|
|
|
|
// Count
|
|
Count(index, field, view string, shard uint64) (uint64, error)
|
|
|
|
// Max
|
|
Max(index, field, view string, shard uint64) (uint64, error)
|
|
|
|
// Min
|
|
Min(index, field, view string, shard uint64) (uint64, bool, error)
|
|
|
|
// UnionInPlace
|
|
UnionInPlace(index, field, view string, shard uint64, others ...*roaring.Bitmap) error
|
|
|
|
// CountRange
|
|
CountRange(index, field, view string, shard uint64, start, end uint64) (uint64, error)
|
|
|
|
// OffsetRange
|
|
OffsetRange(index, field, view string, shard uint64, offset, start, end uint64) (*roaring.Bitmap, error)
|
|
|
|
// ImportRoaringBits does efficient bulk import using rit, a roaring.RoaringIterator.
|
|
//
|
|
// See the roaring package for details of the RoaringIterator.
|
|
//
|
|
// If clear is true, the bits from rit are cleared, otherwise they are set in the
|
|
// specifed fragment.
|
|
//
|
|
// The data argument can be nil, its ignored for RBF/BadgerTx. It is supplied to
|
|
// RoaringTx.ImportRoaringBits() in fragment.go fragment.fillFragmentFromArchive()
|
|
// to do the traditional fragment.readStorageFromArchive() which
|
|
// does some in memory field/view/fragment metadata updates.
|
|
// It makes blueGreenTx testing viable too.
|
|
//
|
|
// ImportRoaringBits return values changed and rowSet may be inaccurate if
|
|
// the data []byte is supplied (the RoaringTx implementation neglects this for speed).
|
|
ImportRoaringBits(index, field, view string, shard uint64, rit roaring.RoaringIterator, clear bool, log bool, rowSize uint64, data []byte) (changed int, rowSet map[uint64]int, err error)
|
|
|
|
RoaringBitmapReader(index, field, view string, shard uint64, fragmentPathForRoaring string) (r io.ReadCloser, sz int64, err error)
|
|
|
|
// Group returns nil or the TxGroup that this Tx is a part of.
|
|
Group() *TxGroup
|
|
|
|
// Dump is for debugging, what does this Tx see as its database?
|
|
Dump(short bool, shard uint64)
|
|
|
|
// Options returns the options used to create this Tx. This
|
|
// can be implementd by embedding Txo, and Txo provides the
|
|
// Options() method.
|
|
Options() Txo
|
|
|
|
// Sn retreives the serial number of the Tx.
|
|
Sn() int64
|
|
|
|
// GetSortedFieldViewList gets the set of FieldView(s)
|
|
GetSortedFieldViewList(idx *Index, shard uint64) (fvs []txkey.FieldView, err error)
|
|
|
|
GetFieldSizeBytes(index, field string) (uint64, error)
|
|
}
|
|
|
|
// Closer is used by Finders
|
|
type Closer interface {
|
|
Close()
|
|
}
|
|
|
|
type Dumper interface {
|
|
// Dump is for debugging, what does this Tx see as its database?
|
|
AllDump()
|
|
}
|
|
|
|
// TxStore has operations that will create and commit multiple
|
|
// Tx on a backing store.
|
|
type TxStore interface {
|
|
|
|
// DeleteFragment deletes all the containers in a fragment.
|
|
//
|
|
// This is not in a Tx because it will often do too many deletes for a single
|
|
// transaction, and clients would be suprised to find their Tx had already
|
|
// been commited and they are getting an error on double-Commit.
|
|
// Instead each TxStore implementation creates and commits as many
|
|
// transactions as needed.
|
|
//
|
|
// Argument frag should be passed by any RoaringTx user, but for RBF/Badger it can be nil.
|
|
// If not nil, it must be of type *fragment. If frag is supplied, then
|
|
// index must be equal to frag.index, field equal to frag.field, view equal
|
|
// to frag.view, and shard equal to frag.shard.
|
|
//
|
|
DeleteFragment(index, field, view string, shard uint64, frag interface{}) error
|
|
|
|
DeleteField(index, field string) error
|
|
|
|
// Close shuts down the database.
|
|
Close() error
|
|
}
|
|
|
|
// RawRoaringData used by ImportRoaringBits.
|
|
// must be consumable by roaring.newRoaringIterator()
|
|
type RawRoaringData struct {
|
|
data []byte
|
|
}
|
|
|
|
func (rr *RawRoaringData) Iterator() (roaring.RoaringIterator, error) {
|
|
return roaring.NewRoaringIterator(rr.data)
|
|
}
|
|
|
|
// GenericApplyFilter implements ApplyFilter in terms of tx.ContainerIterator,
|
|
// as a convenience if a Tx backend hasn't implemented this new function yet.
|
|
func GenericApplyFilter(tx Tx, index, field, view string, shard uint64, ckey uint64, filter roaring.BitmapFilter) (err error) {
|
|
iter, _, err := tx.ContainerIterator(index, field, view, shard, ckey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// ApplyFilterToIterator closes the iterator for us.
|
|
return roaring.ApplyFilterToIterator(filter, iter)
|
|
}
|