Documentation
¶
Index ¶
- Constants
- Variables
- type BloomMeta
- type CleanupStats
- type CompactionConfig
- type CompactionJob
- type CompactionJobType
- type CompactionLogPayload
- type Compactor
- type CompactorOptions
- type DB
- func (db *DB) Close() error
- func (db *DB) OpenCompactor(ctx context.Context, opts CompactorOptions) (*Compactor, error)
- func (db *DB) OpenRetentionCompactor(ctx context.Context, opts RetentionCompactorOptions) (*RetentionCompactor, error)
- func (db *DB) OpenWriter(ctx context.Context, opts WriterOptions) (*Writer, error)
- type DBOptions
- type Iterator
- type IteratorOptions
- type KV
- type Manifest
- type Reader
- func (r *Reader) BlobCacheStats() internal.BlobCacheStats
- func (r *Reader) Close() error
- func (r *Reader) Get(ctx context.Context, key []byte) (value []byte, found bool, err error)
- func (r *Reader) Manifest() *Manifest
- func (r *Reader) ManifestLogCacheStats() cachestore.ManifestLogCacheStats
- func (r *Reader) ManifestUnsafe() *Manifest
- func (r *Reader) NewIterator(ctx context.Context, opts IteratorOptions) (*Iterator, error)
- func (r *Reader) Refresh(ctx context.Context) (err error)
- func (r *Reader) RefreshAndPrefetchSSTs(ctx context.Context) error
- func (r *Reader) SSTCacheStats() SSTCacheStats
- func (r *Reader) Scan(ctx context.Context, minKey, maxKey []byte) (out []KV, err error)
- func (r *Reader) ScanLimit(ctx context.Context, minKey, maxKey []byte, limit int) (out []KV, err error)
- type ReaderMetrics
- func (m *ReaderMetrics) ObserveBlobFetch(d time.Duration, sizeBytes int, cacheHit bool, err error)
- func (m *ReaderMetrics) ObserveGet(d time.Duration, found bool, err error)
- func (m *ReaderMetrics) ObserveRefresh(d time.Duration, err error)
- func (m *ReaderMetrics) ObserveSSTCacheLookup(hit bool)
- func (m *ReaderMetrics) ObserveSSTDownload(d time.Duration, sizeBytes int64, err error)
- func (m *ReaderMetrics) ObserveSSTRangeBlockCacheLookup(hit bool)
- func (m *ReaderMetrics) ObserveSSTRangeRead(d time.Duration, sizeBytes int64, err error)
- func (m *ReaderMetrics) ObserveScan(d time.Duration, resultCount int, err error)
- func (m *ReaderMetrics) ObserveScanLimit(d time.Duration, resultCount int, err error)
- type ReaderOpenOptions
- type ReaderOptions
- type RetentionCompactor
- func (c *RetentionCompactor) Close() error
- func (c *RetentionCompactor) IsFenced() bool
- func (c *RetentionCompactor) Refresh(ctx context.Context) error
- func (c *RetentionCompactor) RunCleanup(ctx context.Context) error
- func (c *RetentionCompactor) Start()
- func (c *RetentionCompactor) Stats() RetentionCompactorStats
- func (c *RetentionCompactor) Stop()
- type RetentionCompactorMode
- type RetentionCompactorOptions
- type RetentionCompactorStats
- type SSTCache
- type SSTCacheStats
- type SSTHashSigner
- type SSTHashVerifier
- type SSTIterator
- type SSTMeta
- type SSTSignature
- type SSTWriterOptions
- type SortedRun
- type TailOptions
- type TailingReader
- func (tr *TailingReader) Close() error
- func (tr *TailingReader) Get(ctx context.Context, key []byte) ([]byte, bool, error)
- func (tr *TailingReader) LastRefresh() time.Time
- func (tr *TailingReader) Manifest() *Manifest
- func (tr *TailingReader) NewIterator(ctx context.Context, opts IteratorOptions) (*Iterator, error)
- func (tr *TailingReader) Reader() *Reader
- func (tr *TailingReader) Refresh(ctx context.Context) error
- func (tr *TailingReader) Scan(ctx context.Context, minKey, maxKey []byte) ([]KV, error)
- func (tr *TailingReader) ScanLimit(ctx context.Context, minKey, maxKey []byte, limit int) ([]KV, error)
- func (tr *TailingReader) Start() error
- func (tr *TailingReader) Stop()
- func (tr *TailingReader) Tail(ctx context.Context, opts TailOptions, handler func(KV) error) error
- func (tr *TailingReader) TailChannel(ctx context.Context, opts TailOptions) (<-chan KV, <-chan error)
- type TailingReaderOpenOptions
- type TailingReaderOptions
- type Writer
- func (w *Writer) Close() error
- func (w *Writer) Delete(key []byte) error
- func (w *Writer) DeleteWithTTL(key []byte, ttl time.Duration) error
- func (w *Writer) Flush(ctx context.Context) error
- func (w *Writer) Put(key, value []byte) error
- func (w *Writer) PutWithTTL(key, value []byte, ttl time.Duration) error
- type WriterMetrics
- func (m *WriterMetrics) ObserveBackpressure()
- func (m *WriterMetrics) ObserveDelete()
- func (m *WriterMetrics) ObserveFlush(d time.Duration, err error)
- func (m *WriterMetrics) ObserveFlushBytes(sizeBytes int64)
- func (m *WriterMetrics) ObservePut(err error)
- func (m *WriterMetrics) ObservePutBlob(sizeBytes int, d time.Duration, err error)
- type WriterOptions
Constants ¶
const CompactionMaxIterations = 100
Variables ¶
var ErrBackpressure = errors.New("writer backpressure")
var ErrEmptyIterator = errors.New("iterator produced no entries")
var ErrOutOfOrder = errors.New("iterator out of order")
var ErrTailingReaderStopped = errors.New("tailing reader stopped")
Functions ¶
This section is empty.
Types ¶
type CleanupStats ¶
type CompactionConfig ¶
type CompactionConfig = manifest.CompactionConfig
type CompactionJob ¶
type CompactionJob struct {
Type CompactionJobType
InputSSTs []string
InputRuns []uint32
OutputRun *SortedRun
}
type CompactionJobType ¶
type CompactionJobType int
const ( CompactionL0Flush CompactionJobType = iota CompactionConsecutiveMerge )
type CompactionLogPayload ¶
type CompactionLogPayload = manifest.CompactionLogPayload
type Compactor ¶
type Compactor struct {
// contains filtered or unexported fields
}
Compactor merges SSTs into sorted runs in the background.
func (*Compactor) FenceToken ¶
func (c *Compactor) FenceToken() *manifest.FenceToken
func (*Compactor) RunCompaction ¶
RunCompaction performs a compaction cycle and returns when no work remains.
type CompactorOptions ¶
type CompactorOptions struct {
L0CompactionThreshold int
MinSources int
MaxSources int
SizeThreshold int
BloomBitsPerKey int
BlockSize int
Compression string
TargetSSTSize int64
// ValidateSSTChecksum verifies SST checksums before compaction.
ValidateSSTChecksum bool
// SSTHashVerifier verifies SST signatures when present.
SSTHashVerifier SSTHashVerifier
CheckInterval time.Duration
OnCompactionStart func(CompactionJob)
OnCompactionEnd func(CompactionJob, error)
OwnerID string
// GCMarkStorage allows using a custom storage backend for GC mark state.
GCMarkStorage manifest.GCMarkStorage
}
func DefaultCompactorOptions ¶
func DefaultCompactorOptions() CompactorOptions
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB encapsulates manifest state for writers and compactors operating on a single bucket/prefix. Use OpenDB once, then call db.OpenWriter and/or db.OpenCompactor.
func (*DB) OpenCompactor ¶
OpenCompactor opens a compactor instance from the DB.
func (*DB) OpenRetentionCompactor ¶
func (db *DB) OpenRetentionCompactor(ctx context.Context, opts RetentionCompactorOptions) (*RetentionCompactor, error)
OpenRetentionCompactor opens a retention compactor for this DB.
func (*DB) OpenWriter ¶
OpenWriter opens a writer instance from the DB.
type DBOptions ¶
type DBOptions struct {
// ManifestStorage allows using a custom manifest storage backend.
// If nil, the blob store is used.
ManifestStorage manifest.Storage
// GCMarkStorage allows using a custom storage backend for GC mark state.
// If nil, the blob store is used.
GCMarkStorage manifest.GCMarkStorage
}
DBOptions configures a DB instance.
type IteratorOptions ¶
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
func OpenReader ¶
func OpenReader(ctx context.Context, store *blobstore.Store, opts ReaderOpenOptions) (*Reader, error)
OpenReader opens a read-only handle.
func (*Reader) BlobCacheStats ¶
func (r *Reader) BlobCacheStats() internal.BlobCacheStats
func (*Reader) ManifestLogCacheStats ¶
func (r *Reader) ManifestLogCacheStats() cachestore.ManifestLogCacheStats
func (*Reader) ManifestUnsafe ¶
func (*Reader) NewIterator ¶
func (*Reader) RefreshAndPrefetchSSTs ¶
RefreshAndPrefetchSSTs refreshes the manifest and prefetches any new SSTs that were added since the last refresh. This is useful for keeping the cache warm with new data. Call this periodically if you want to proactively cache new SSTs as they are written.
WARNING: If you use this method, avoid calling Refresh() separately. Mixing RefreshAndPrefetchSSTs with manual Refresh calls may cause some SSTs to be missed during prefetch, as the function only prefetches SSTs that are new relative to the manifest state before the refresh. Choose one approach and use it consistently.
func (*Reader) SSTCacheStats ¶
func (r *Reader) SSTCacheStats() SSTCacheStats
type ReaderMetrics ¶ added in v0.0.2
type ReaderMetrics struct {
RefreshTotal prometheus.Counter
RefreshErrors prometheus.Counter
RefreshLatency prometheus.Histogram
GetTotal prometheus.Counter
GetErrors prometheus.Counter
GetHits prometheus.Counter
GetMisses prometheus.Counter
GetLatency prometheus.Histogram
ScanTotal prometheus.Counter
ScanErrors prometheus.Counter
ScanLatency prometheus.Histogram
ScanResults prometheus.Counter
ScanLimitTotal prometheus.Counter
ScanLimitErrors prometheus.Counter
ScanLimitLatency prometheus.Histogram
ScanLimitResults prometheus.Counter
BlobFetchTotal prometheus.Counter
BlobFetchErrors prometheus.Counter
BlobFetchLatency prometheus.Histogram
BlobCacheHits prometheus.Counter
BlobCacheMisses prometheus.Counter
BlobBytesTotal prometheus.Counter
SSTCacheHits prometheus.Counter
SSTCacheMisses prometheus.Counter
SSTDownloadTotal prometheus.Counter
SSTDownloadErrors prometheus.Counter
SSTDownloadLatency prometheus.Histogram
SSTDownloadBytes prometheus.Counter
SSTRangeBlockCacheHits prometheus.Counter
SSTRangeBlockCacheMisses prometheus.Counter
SSTRangeReadTotal prometheus.Counter
SSTRangeReadErrors prometheus.Counter
SSTRangeReadLatency prometheus.Histogram
SSTRangeReadBytes prometheus.Counter
}
func DefaultReaderMetrics ¶ added in v0.0.2
func DefaultReaderMetrics(constLabels prometheus.Labels) *ReaderMetrics
func (*ReaderMetrics) ObserveBlobFetch ¶ added in v0.0.2
func (*ReaderMetrics) ObserveGet ¶ added in v0.0.2
func (m *ReaderMetrics) ObserveGet(d time.Duration, found bool, err error)
func (*ReaderMetrics) ObserveRefresh ¶ added in v0.0.2
func (m *ReaderMetrics) ObserveRefresh(d time.Duration, err error)
func (*ReaderMetrics) ObserveSSTCacheLookup ¶ added in v0.0.2
func (m *ReaderMetrics) ObserveSSTCacheLookup(hit bool)
func (*ReaderMetrics) ObserveSSTDownload ¶ added in v0.0.2
func (m *ReaderMetrics) ObserveSSTDownload(d time.Duration, sizeBytes int64, err error)
func (*ReaderMetrics) ObserveSSTRangeBlockCacheLookup ¶ added in v0.0.2
func (m *ReaderMetrics) ObserveSSTRangeBlockCacheLookup(hit bool)
func (*ReaderMetrics) ObserveSSTRangeRead ¶ added in v0.0.2
func (m *ReaderMetrics) ObserveSSTRangeRead(d time.Duration, sizeBytes int64, err error)
func (*ReaderMetrics) ObserveScan ¶ added in v0.0.2
func (m *ReaderMetrics) ObserveScan(d time.Duration, resultCount int, err error)
func (*ReaderMetrics) ObserveScanLimit ¶ added in v0.0.2
func (m *ReaderMetrics) ObserveScanLimit(d time.Duration, resultCount int, err error)
type ReaderOpenOptions ¶
type ReaderOpenOptions struct {
// CacheDir is the directory for disk caches (required).
CacheDir string
// SSTCacheSize is the maximum bytes for SST cache (default 1GB).
SSTCacheSize int64
// BlobCacheSize is the maximum bytes for blob cache (default 1GB).
BlobCacheSize int64
// BlobCacheMaxItemSize is the maximum size per item in the blob cache.
BlobCacheMaxItemSize int64
// BlockCacheSize is the maximum bytes for the in-memory block cache used
// when range-reading SSTs. Default 0 disables the block cache.
BlockCacheSize int64
// AllowUnverifiedRangeRead permits range-reading SSTs without verifying
// full-file checksums or signatures.
AllowUnverifiedRangeRead bool
// RangeReadMinSSTSize is the minimum SST size (bytes) required to use
// range-read + block cache. Default 0 means no size threshold.
RangeReadMinSSTSize int64
// ValidateSSTChecksum verifies SST checksums on first download.
// If enabled and checksum is missing or mismatched, reads fail.
ValidateSSTChecksum bool
// SSTHashVerifier verifies SST signatures when present.
// If provided and the SST has a signature, verification is enforced.
SSTHashVerifier SSTHashVerifier
Metrics *ReaderMetrics
BlobReadOptions config.BlobReadOptions
ManifestStorage manifest.Storage
}
ReaderOpenOptions configures a read-only handle.
func DefaultReaderOpenOptions ¶
func DefaultReaderOpenOptions() ReaderOpenOptions
DefaultReaderOpenOptions returns sane defaults for ReaderOpenOptions.
type ReaderOptions ¶
type ReaderOptions struct {
// CacheDir is the directory for disk caches.
CacheDir string
// SSTCache is an optional pre-created SST cache.
SSTCache diskcache.RefCountedCache
// SSTCacheSize is the maximum bytes for SST cache (default 1GB).
SSTCacheSize int64
// BlobCache is an optional pre-created blob cache.
BlobCache internal.BlobCache
// BlobCacheSize is the maximum bytes for blob cache (default 1GB).
BlobCacheSize int64
// BlobCacheMaxItemSize is the maximum size per item in the blob cache.
// Items larger than this will not be cached. Default 0 means no limit.
BlobCacheMaxItemSize int64
// BlockCacheSize is the maximum bytes for the in-memory block cache used
// when range-reading SSTs. Default 0 disables the block cache.
BlockCacheSize int64
// AllowUnverifiedRangeRead permits range-reading SSTs without verifying
// full-file checksums or signatures.
AllowUnverifiedRangeRead bool
// RangeReadMinSSTSize is the minimum SST size (bytes) required to use
// range-read + block cache. Default 0 means no size threshold.
RangeReadMinSSTSize int64
ValueStorageConfig config.ValueStorageConfig
ManifestStorage manifest.Storage
ManifestLogCache cachestore.ManifestLogCache
ManifestLogCacheSize int
DisableManifestCache bool
// ValidateSSTChecksum verifies SST checksums on first download.
// If enabled and checksum is missing or mismatched, reads fail.
ValidateSSTChecksum bool
// SSTHashVerifier verifies SST signatures when present.
// If provided and the SST has a signature, verification is enforced.
SSTHashVerifier SSTHashVerifier
Metrics *ReaderMetrics
}
func DefaultReaderOptions ¶
func DefaultReaderOptions() ReaderOptions
type RetentionCompactor ¶
type RetentionCompactor struct {
// contains filtered or unexported fields
}
func (*RetentionCompactor) Close ¶
func (c *RetentionCompactor) Close() error
func (*RetentionCompactor) IsFenced ¶
func (c *RetentionCompactor) IsFenced() bool
func (*RetentionCompactor) Refresh ¶
func (c *RetentionCompactor) Refresh(ctx context.Context) error
func (*RetentionCompactor) RunCleanup ¶
func (c *RetentionCompactor) RunCleanup(ctx context.Context) error
func (*RetentionCompactor) Start ¶
func (c *RetentionCompactor) Start()
func (*RetentionCompactor) Stats ¶
func (c *RetentionCompactor) Stats() RetentionCompactorStats
func (*RetentionCompactor) Stop ¶
func (c *RetentionCompactor) Stop()
type RetentionCompactorMode ¶
type RetentionCompactorMode int
const ( CompactByAge RetentionCompactorMode = iota CompactByTimeWindow )
type RetentionCompactorOptions ¶
type RetentionCompactorOptions struct {
Mode RetentionCompactorMode
RetentionPeriod time.Duration
RetentionCount int
CheckInterval time.Duration
SegmentDuration time.Duration
OnCleanup func(CleanupStats)
OnCleanupError func(error)
// GCMarkStorage allows using a custom storage backend for GC mark state.
// If nil, the blob store is used.
GCMarkStorage manifest.GCMarkStorage
}
func DefaultRetentionCompactorOptions ¶
func DefaultRetentionCompactorOptions() RetentionCompactorOptions
type RetentionCompactorStats ¶
type SSTCache ¶
type SSTCache = diskcache.RefCountedCache
SSTCache is an alias to diskcache.RefCountedCache for caching SST file data.
type SSTCacheStats ¶
SSTCacheStats is an alias to diskcache.Stats for SST cache statistics.
type SSTHashSigner ¶
type SSTHashSigner interface {
Algorithm() string
KeyID() string
SignHash(hash []byte) ([]byte, error)
}
SSTHashSigner signs SST hash bytes for integrity verification.
type SSTHashVerifier ¶
type SSTHashVerifier interface {
VerifyHash(hash []byte, sig SSTSignature) error
}
SSTHashVerifier verifies SST hash signatures for integrity checks.
type SSTIterator ¶
type SSTSignature ¶
type SSTSignature = manifest.SSTSignature
type SSTWriterOptions ¶
type SSTWriterOptions struct {
BloomBitsPerKey int
BlockSize int
Compression string
Signer SSTHashSigner
}
type TailOptions ¶
type TailOptions struct {
// MinKey and MaxKey constrain the tailing range (inclusive bounds).
MinKey []byte
MaxKey []byte
// StartAfterKey resumes tailing from the next key after this value.
// If set, it overrides MinKey as the lower bound.
StartAfterKey []byte
// PollInterval controls how often to check for new keys.
PollInterval time.Duration
}
TailOptions controls tailing behavior for a TailingReader.
type TailingReader ¶
type TailingReader struct {
// contains filtered or unexported fields
}
TailingReader is a read-only handle that refreshes manifests periodically and can tail new keys as they appear in object storage.
func OpenTailingReader ¶
func OpenTailingReader(ctx context.Context, store *blobstore.Store, opts TailingReaderOpenOptions) (*TailingReader, error)
OpenTailingReader opens a tailing reader handle.
func (*TailingReader) Close ¶
func (tr *TailingReader) Close() error
Close stops background refresh and closes the underlying reader.
func (*TailingReader) LastRefresh ¶
func (tr *TailingReader) LastRefresh() time.Time
func (*TailingReader) Manifest ¶
func (tr *TailingReader) Manifest() *Manifest
Manifest returns a snapshot of the current manifest.
func (*TailingReader) NewIterator ¶
func (tr *TailingReader) NewIterator(ctx context.Context, opts IteratorOptions) (*Iterator, error)
NewIterator returns an iterator over the requested key range.
func (*TailingReader) Reader ¶
func (tr *TailingReader) Reader() *Reader
Reader exposes the underlying Reader.
func (*TailingReader) ScanLimit ¶
func (tr *TailingReader) ScanLimit(ctx context.Context, minKey, maxKey []byte, limit int) ([]KV, error)
ScanLimit returns up to limit key-value pairs in the given range.
func (*TailingReader) Start ¶
func (tr *TailingReader) Start() error
func (*TailingReader) Stop ¶
func (tr *TailingReader) Stop()
Stop terminates the background refresh loop.
func (*TailingReader) Tail ¶
func (tr *TailingReader) Tail(ctx context.Context, opts TailOptions, handler func(KV) error) error
Tail continuously scans for new keys and calls handler for each result.
func (*TailingReader) TailChannel ¶
func (tr *TailingReader) TailChannel(ctx context.Context, opts TailOptions) (<-chan KV, <-chan error)
TailChannel returns a channel of KV updates and an error channel.
type TailingReaderOpenOptions ¶
type TailingReaderOpenOptions struct {
RefreshInterval time.Duration
OnRefresh func()
OnRefreshError func(error)
ReaderOptions ReaderOpenOptions
}
TailingReaderOpenOptions configures a tailing reader.
func DefaultTailingReaderOpenOptions ¶
func DefaultTailingReaderOpenOptions() TailingReaderOpenOptions
DefaultTailingReaderOpenOptions returns sane defaults for TailingReaderOpenOptions.
type TailingReaderOptions ¶
type TailingReaderOptions struct {
RefreshInterval time.Duration
OnRefresh func()
OnRefreshError func(error)
ReaderOptions ReaderOptions
}
func DefaultTailingReaderOptions ¶
func DefaultTailingReaderOptions() TailingReaderOptions
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer provides write access to the database.
func (*Writer) DeleteWithTTL ¶
DeleteWithTTL marks a key as deleted with a time-to-live duration.
type WriterMetrics ¶ added in v0.0.2
type WriterMetrics struct {
FlushTotal prometheus.Counter
FlushErrors prometheus.Counter
FlushLatency prometheus.Histogram
FlushBytes prometheus.Counter
PutTotal prometheus.Counter
PutErrors prometheus.Counter
BackPressureTotal prometheus.Counter
PutBlobTotal prometheus.Counter
PutBlobErrors prometheus.Counter
PutBlobLatency prometheus.Histogram
BlobBytesTotal prometheus.Counter
DeleteTotal prometheus.Counter
}
func DefaultWriterMetrics ¶ added in v0.0.2
func DefaultWriterMetrics(constLabels prometheus.Labels) *WriterMetrics
func (*WriterMetrics) ObserveBackpressure ¶ added in v0.0.2
func (m *WriterMetrics) ObserveBackpressure()
func (*WriterMetrics) ObserveDelete ¶ added in v0.0.2
func (m *WriterMetrics) ObserveDelete()
func (*WriterMetrics) ObserveFlush ¶ added in v0.0.2
func (m *WriterMetrics) ObserveFlush(d time.Duration, err error)
func (*WriterMetrics) ObserveFlushBytes ¶ added in v0.0.2
func (m *WriterMetrics) ObserveFlushBytes(sizeBytes int64)
func (*WriterMetrics) ObservePut ¶ added in v0.0.2
func (m *WriterMetrics) ObservePut(err error)
func (*WriterMetrics) ObservePutBlob ¶ added in v0.0.2
func (m *WriterMetrics) ObservePutBlob(sizeBytes int, d time.Duration, err error)
type WriterOptions ¶
type WriterOptions struct {
MemtableSize int64
FlushInterval time.Duration
BloomBitsPerKey int
BlockSize int
Compression string
// MaxImmutableMemtables limits pending memtables waiting to be flushed.
// When the limit is reached, writers return ErrBackpressure.
MaxImmutableMemtables int
OnFlushError func(error)
ValueStorage config.ValueStorageConfig
OwnerID string
Metrics *WriterMetrics
}
func DefaultWriterOptions ¶
func DefaultWriterOptions() WriterOptions
Source Files
¶
- api.go
- block_cache.go
- bloom_container.go
- compactor.go
- crc.go
- db.go
- k_merge_iter.go
- keyutil.go
- metrics.go
- options.go
- reader.go
- reader_api.go
- reader_prefetch.go
- retention_compactor.go
- sst.go
- sst_cache.go
- sst_gc_marks.go
- sst_gc_sweeper.go
- sst_range_readable.go
- sst_signer.go
- sst_stream.go
- tailing_reader.go
- tailing_reader_api.go
- writer.go
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
eventhub-minio/consumer
command
|
|
|
eventhub-minio/producer
command
|
|
|
kvfile
command
|
|
|
wal-azblob
command
|
|