Documentation
¶
Overview ¶
Package filter provides row-level predicates over format.XRow used by pipe.Copy to select which logical transactions to keep when streaming rows from a reader to a writer.
Filters must NOT mutate the row. The row is logically read-only; callers (and pipe.Copy) rely on this when re-emitting the row downstream. Rows are passed by value, so a filter could not mutate the caller's row anyway — but the contract still holds for clarity.
Filters work on header fields only. None of the constructors below touches BodyRaw — keeping the decode-on-demand promise of the format package intact.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Filter ¶
Filter is a row-level predicate. It returns true to keep the row. Implementations MUST treat the row as read-only.
func And ¶
And returns a Filter that matches when every supplied filter matches. Empty argument list is vacuously true (matches every row).
Example ¶
ExampleAnd composes predicates: keep only INSERT/REPLACE rows from replica 1. And matches a row only when every supplied filter matches it.
package main
import (
"fmt"
"github.com/tarantool/go-iproto"
"github.com/tarantool/go-xlog/filter"
"github.com/tarantool/go-xlog/format"
)
// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
return []format.XRow{
{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
}
}
// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
var lines []string
for _, r := range sampleRows() {
if f(r) {
lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
}
}
return lines
}
func main() {
for _, s := range kept(filter.And(
filter.ReplicaIDs(1),
filter.Types(iproto.IPROTO_INSERT, iproto.IPROTO_REPLACE),
)) {
fmt.Println(s)
}
}
Output: INSERT replica=1 lsn=1 REPLACE replica=1 lsn=2 REPLACE replica=1 lsn=3
func FromVClock ¶
FromVClock keeps rows whose LSN is strictly greater than v[r.ReplicaID]. A replica missing from v is treated as LSN 0, so every positive LSN for that replica passes. Useful for "tail from a given vclock onward".
Example ¶
ExampleFromVClock keeps rows strictly after a per-replica position — the "tail from a given vclock onward" selector. Here replica 1 is advanced past LSN 2 (so only its LSN 3 survives) while replica 2 is absent from the vclock and therefore treated as LSN 0 (so all of its positive LSNs pass).
package main
import (
"fmt"
"github.com/tarantool/go-iproto"
"github.com/tarantool/go-xlog/filter"
"github.com/tarantool/go-xlog/format"
)
// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
return []format.XRow{
{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
}
}
// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
var lines []string
for _, r := range sampleRows() {
if f(r) {
lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
}
}
return lines
}
func main() {
for _, s := range kept(filter.FromVClock(format.VClock{1: 2})) {
fmt.Println(s)
}
}
Output: DELETE replica=2 lsn=1 INSERT replica=2 lsn=2 REPLACE replica=1 lsn=3
func LSNRange ¶
LSNRange keeps rows whose ReplicaID == rep AND lo <= LSN <= hi (inclusive on both ends).
Example ¶
ExampleLSNRange keeps rows for one replica whose LSN falls in an inclusive [lo, hi] window.
package main
import (
"fmt"
"github.com/tarantool/go-iproto"
"github.com/tarantool/go-xlog/filter"
"github.com/tarantool/go-xlog/format"
)
// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
return []format.XRow{
{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
}
}
// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
var lines []string
for _, r := range sampleRows() {
if f(r) {
lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
}
}
return lines
}
func main() {
for _, s := range kept(filter.LSNRange(1, 2, 3)) {
fmt.Println(s)
}
}
Output: REPLACE replica=1 lsn=2 REPLACE replica=1 lsn=3
func Not ¶
Not returns a Filter that matches when f does not match.
Example ¶
ExampleNot inverts a predicate: keep every row that is NOT a DELETE.
package main
import (
"fmt"
"github.com/tarantool/go-iproto"
"github.com/tarantool/go-xlog/filter"
"github.com/tarantool/go-xlog/format"
)
// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
return []format.XRow{
{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
}
}
// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
var lines []string
for _, r := range sampleRows() {
if f(r) {
lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
}
}
return lines
}
func main() {
for _, s := range kept(filter.Not(filter.Types(iproto.IPROTO_DELETE))) {
fmt.Println(s)
}
}
Output: INSERT replica=1 lsn=1 REPLACE replica=1 lsn=2 INSERT replica=2 lsn=2 REPLACE replica=1 lsn=3
func Or ¶
Or returns a Filter that matches when at least one supplied filter matches. Empty argument list is vacuously false (matches nothing).
Example ¶
ExampleOr keeps a row when at least one supplied filter matches it.
package main
import (
"fmt"
"github.com/tarantool/go-iproto"
"github.com/tarantool/go-xlog/filter"
"github.com/tarantool/go-xlog/format"
)
// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
return []format.XRow{
{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
}
}
// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
var lines []string
for _, r := range sampleRows() {
if f(r) {
lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
}
}
return lines
}
func main() {
for _, s := range kept(filter.Or(
filter.Types(iproto.IPROTO_DELETE),
filter.ReplicaIDs(2),
)) {
fmt.Println(s)
}
}
Output: DELETE replica=2 lsn=1 INSERT replica=2 lsn=2
func ReplicaIDs ¶
ReplicaIDs keeps rows whose ReplicaID is in the supplied set. An empty argument list keeps nothing — this matches the "filter is a positive selector" intent.
Example ¶
ExampleReplicaIDs keeps only rows originating from the given replica ids.
package main
import (
"fmt"
"github.com/tarantool/go-iproto"
"github.com/tarantool/go-xlog/filter"
"github.com/tarantool/go-xlog/format"
)
// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
return []format.XRow{
{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
}
}
// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
var lines []string
for _, r := range sampleRows() {
if f(r) {
lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
}
}
return lines
}
func main() {
for _, s := range kept(filter.ReplicaIDs(2)) {
fmt.Println(s)
}
}
Output: DELETE replica=2 lsn=1 INSERT replica=2 lsn=2
func Types ¶
Types keeps rows whose Type is in the supplied set. Empty argument list keeps nothing (same convention as ReplicaIDs).
Example ¶
ExampleTypes keeps only rows whose request type is in the given set.
package main
import (
"fmt"
"github.com/tarantool/go-iproto"
"github.com/tarantool/go-xlog/filter"
"github.com/tarantool/go-xlog/format"
)
// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
return []format.XRow{
{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
}
}
// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
var lines []string
for _, r := range sampleRows() {
if f(r) {
lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
}
}
return lines
}
func main() {
for _, s := range kept(filter.Types(iproto.IPROTO_INSERT)) {
fmt.Println(s)
}
}
Output: INSERT replica=1 lsn=1 INSERT replica=2 lsn=2
func UntilVClock ¶
UntilVClock keeps rows whose LSN is <= v[r.ReplicaID]. A replica missing from v is treated as LSN 0, so for that replica only LSN==0 passes (effectively nothing in normal logs). Inverse-ish of FromVClock — note the boundary: FromVClock(v) uses strict >, UntilVClock(v) uses <=, so the row at exactly v[id] belongs to UntilVClock.