snapshot of https://github.com/seaweedfs/seaweedfs.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
This commit is contained in:
510
weed/filer/redis3/ItemList.go
Normal file
510
weed/filer/redis3/ItemList.go
Normal file
@@ -0,0 +1,510 @@
|
||||
package redis3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/seaweedfs/seaweedfs/weed/util/skiplist"
|
||||
)
|
||||
|
||||
type ItemList struct {
|
||||
skipList *skiplist.SkipList
|
||||
batchSize int
|
||||
client redis.UniversalClient
|
||||
prefix string
|
||||
}
|
||||
|
||||
/*
|
||||
Be reluctant to create new nodes. Try to fit into either previous node or next node.
|
||||
Prefer to add to previous node.
|
||||
|
||||
There are multiple cases after finding the name for greater or equal node
|
||||
1. found and node.Key == name
|
||||
The node contains a batch with leading key the same as the name
|
||||
nothing to do
|
||||
2. no such node found or node.Key > name
|
||||
|
||||
if no such node found
|
||||
prevNode = list.LargestNode
|
||||
|
||||
// case 2.1
|
||||
if previousNode contains name
|
||||
nothing to do
|
||||
|
||||
// prefer to add to previous node
|
||||
if prevNode != nil {
|
||||
// case 2.2
|
||||
if prevNode has capacity
|
||||
prevNode.add name, and save
|
||||
return
|
||||
// case 2.3
|
||||
split prevNode by name
|
||||
}
|
||||
|
||||
// case 2.4
|
||||
// merge into next node. Avoid too many nodes if adding data in reverse order.
|
||||
if nextNode is not nil and nextNode has capacity
|
||||
delete nextNode.Key
|
||||
nextNode.Key = name
|
||||
nextNode.batch.add name
|
||||
insert nodeNode.Key
|
||||
return
|
||||
|
||||
// case 2.5
|
||||
if prevNode is nil
|
||||
insert new node with key = name, value = batch{name}
|
||||
return
|
||||
|
||||
*/
|
||||
|
||||
func (nl *ItemList) canAddMember(node *skiplist.SkipListElementReference, name string) (alreadyContains bool, nodeSize int, err error) {
|
||||
ctx := context.Background()
|
||||
pipe := nl.client.TxPipeline()
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
countOperation := pipe.ZLexCount(ctx, key, "-", "+")
|
||||
scoreOperationt := pipe.ZScore(ctx, key, name)
|
||||
if _, err = pipe.Exec(ctx); err != nil && err != redis.Nil {
|
||||
return false, 0, err
|
||||
}
|
||||
if err == redis.Nil {
|
||||
err = nil
|
||||
}
|
||||
alreadyContains = scoreOperationt.Err() == nil
|
||||
nodeSize = int(countOperation.Val())
|
||||
return
|
||||
}
|
||||
|
||||
func (nl *ItemList) WriteName(name string) error {
|
||||
|
||||
lookupKey := []byte(name)
|
||||
prevNode, nextNode, found, err := nl.skipList.FindGreaterOrEqual(lookupKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// case 1: the name already exists as one leading key in the batch
|
||||
if found && bytes.Compare(nextNode.Key, lookupKey) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var prevNodeReference *skiplist.SkipListElementReference
|
||||
if !found {
|
||||
prevNodeReference = nl.skipList.GetLargestNodeReference()
|
||||
}
|
||||
|
||||
if nextNode != nil && prevNode == nil {
|
||||
prevNodeReference = nextNode.Prev
|
||||
}
|
||||
|
||||
if prevNodeReference != nil {
|
||||
alreadyContains, nodeSize, err := nl.canAddMember(prevNodeReference, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if alreadyContains {
|
||||
// case 2.1
|
||||
return nil
|
||||
}
|
||||
|
||||
// case 2.2
|
||||
if nodeSize < nl.batchSize {
|
||||
return nl.NodeAddMember(prevNodeReference, name)
|
||||
}
|
||||
|
||||
// case 2.3
|
||||
x := nl.NodeInnerPosition(prevNodeReference, name)
|
||||
y := nodeSize - x
|
||||
addToX := x <= y
|
||||
// add to a new node
|
||||
if x == 0 || y == 0 {
|
||||
if err := nl.ItemAdd(lookupKey, 0, name); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if addToX {
|
||||
// collect names before name, add them to X
|
||||
namesToX, err := nl.NodeRangeBeforeExclusive(prevNodeReference, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// delete skiplist reference to old node
|
||||
if _, err := nl.skipList.DeleteByKey(prevNodeReference.Key); err != nil {
|
||||
return err
|
||||
}
|
||||
// add namesToY and name to a new X
|
||||
namesToX = append(namesToX, name)
|
||||
if err := nl.ItemAdd([]byte(namesToX[0]), 0, namesToX...); err != nil {
|
||||
return err
|
||||
}
|
||||
// remove names less than name from current Y
|
||||
if err := nl.NodeDeleteBeforeExclusive(prevNodeReference, name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// point skip list to current Y
|
||||
if err := nl.ItemAdd(lookupKey, prevNodeReference.ElementPointer); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
// collect names after name, add them to Y
|
||||
namesToY, err := nl.NodeRangeAfterExclusive(prevNodeReference, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// add namesToY and name to a new Y
|
||||
namesToY = append(namesToY, name)
|
||||
if err := nl.ItemAdd(lookupKey, 0, namesToY...); err != nil {
|
||||
return err
|
||||
}
|
||||
// remove names after name from current X
|
||||
if err := nl.NodeDeleteAfterExclusive(prevNodeReference, name); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// case 2.4
|
||||
if nextNode != nil {
|
||||
nodeSize := nl.NodeSize(nextNode.Reference())
|
||||
if nodeSize < nl.batchSize {
|
||||
if id, err := nl.skipList.DeleteByKey(nextNode.Key); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if err := nl.ItemAdd(lookupKey, id, name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// case 2.5
|
||||
// now prevNode is nil
|
||||
return nl.ItemAdd(lookupKey, 0, name)
|
||||
}
|
||||
|
||||
/*
|
||||
// case 1: exists in nextNode
|
||||
|
||||
if nextNode != nil && nextNode.Key == name {
|
||||
remove from nextNode, update nextNode
|
||||
// TODO: merge with prevNode if possible?
|
||||
return
|
||||
}
|
||||
|
||||
if nextNode is nil
|
||||
|
||||
prevNode = list.Largestnode
|
||||
|
||||
if prevNode == nil and nextNode.Prev != nil
|
||||
|
||||
prevNode = load(nextNode.Prev)
|
||||
|
||||
// case 2: does not exist
|
||||
// case 2.1
|
||||
|
||||
if prevNode == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// case 2.2
|
||||
|
||||
if prevNameBatch does not contain name {
|
||||
return
|
||||
}
|
||||
|
||||
// case 3
|
||||
delete from prevNameBatch
|
||||
if prevNameBatch + nextNode < capacityList
|
||||
|
||||
// case 3.1
|
||||
merge
|
||||
|
||||
else
|
||||
|
||||
// case 3.2
|
||||
update prevNode
|
||||
*/
|
||||
func (nl *ItemList) DeleteName(name string) error {
|
||||
lookupKey := []byte(name)
|
||||
prevNode, nextNode, found, err := nl.skipList.FindGreaterOrEqual(lookupKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// case 1
|
||||
if found && bytes.Compare(nextNode.Key, lookupKey) == 0 {
|
||||
if _, err := nl.skipList.DeleteByKey(nextNode.Key); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := nl.NodeDeleteMember(nextNode.Reference(), name); err != nil {
|
||||
return err
|
||||
}
|
||||
minName := nl.NodeMin(nextNode.Reference())
|
||||
if minName == "" {
|
||||
return nl.NodeDelete(nextNode.Reference())
|
||||
}
|
||||
return nl.ItemAdd([]byte(minName), nextNode.Id)
|
||||
}
|
||||
|
||||
if !found {
|
||||
prevNode, err = nl.skipList.GetLargestNode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if nextNode != nil && prevNode == nil {
|
||||
prevNode, err = nl.skipList.LoadElement(nextNode.Prev)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// case 2
|
||||
if prevNode == nil {
|
||||
// case 2.1
|
||||
return nil
|
||||
}
|
||||
if !nl.NodeContainsItem(prevNode.Reference(), name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// case 3
|
||||
if err := nl.NodeDeleteMember(prevNode.Reference(), name); err != nil {
|
||||
return err
|
||||
}
|
||||
prevSize := nl.NodeSize(prevNode.Reference())
|
||||
if prevSize == 0 {
|
||||
if _, err := nl.skipList.DeleteByKey(prevNode.Key); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
nextSize := nl.NodeSize(nextNode.Reference())
|
||||
if nextSize > 0 && prevSize+nextSize < nl.batchSize {
|
||||
// case 3.1 merge nextNode and prevNode
|
||||
if _, err := nl.skipList.DeleteByKey(nextNode.Key); err != nil {
|
||||
return err
|
||||
}
|
||||
nextNames, err := nl.NodeRangeBeforeExclusive(nextNode.Reference(), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := nl.NodeAddMember(prevNode.Reference(), nextNames...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nl.NodeDelete(nextNode.Reference())
|
||||
} else {
|
||||
// case 3.2 update prevNode
|
||||
// no action to take
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (nl *ItemList) ListNames(startFrom string, visitNamesFn func(name string) bool) error {
|
||||
lookupKey := []byte(startFrom)
|
||||
prevNode, nextNode, found, err := nl.skipList.FindGreaterOrEqual(lookupKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if found && bytes.Compare(nextNode.Key, lookupKey) == 0 {
|
||||
prevNode = nil
|
||||
}
|
||||
if !found {
|
||||
prevNode, err = nl.skipList.GetLargestNode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if prevNode != nil {
|
||||
if !nl.NodeScanInclusiveAfter(prevNode.Reference(), startFrom, visitNamesFn) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
for nextNode != nil {
|
||||
if !nl.NodeScanInclusiveAfter(nextNode.Reference(), startFrom, visitNamesFn) {
|
||||
return nil
|
||||
}
|
||||
nextNode, err = nl.skipList.LoadElement(nextNode.Next[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nl *ItemList) IsEmpty() bool {
|
||||
return nl.skipList.StartLevels[0] == nil
|
||||
}
|
||||
|
||||
func (nl *ItemList) RemoteAllListElement() error {
|
||||
|
||||
t := nl.skipList
|
||||
|
||||
nodeRef := t.StartLevels[0]
|
||||
for nodeRef != nil {
|
||||
node, err := t.LoadElement(nodeRef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
if err := t.DeleteElement(node); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := nl.NodeDelete(node.Reference()); err != nil {
|
||||
return err
|
||||
}
|
||||
nodeRef = node.Next[0]
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (nl *ItemList) NodeContainsItem(node *skiplist.SkipListElementReference, item string) bool {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
_, err := nl.client.ZScore(context.Background(), key, item).Result()
|
||||
if err == redis.Nil {
|
||||
return false
|
||||
}
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (nl *ItemList) NodeSize(node *skiplist.SkipListElementReference) int {
|
||||
if node == nil {
|
||||
return 0
|
||||
}
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
return int(nl.client.ZLexCount(context.Background(), key, "-", "+").Val())
|
||||
}
|
||||
|
||||
func (nl *ItemList) NodeAddMember(node *skiplist.SkipListElementReference, names ...string) error {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
var members []redis.Z
|
||||
for _, name := range names {
|
||||
members = append(members, redis.Z{
|
||||
Score: 0,
|
||||
Member: name,
|
||||
})
|
||||
}
|
||||
return nl.client.ZAddNX(context.Background(), key, members...).Err()
|
||||
}
|
||||
func (nl *ItemList) NodeDeleteMember(node *skiplist.SkipListElementReference, name string) error {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
return nl.client.ZRem(context.Background(), key, name).Err()
|
||||
}
|
||||
|
||||
func (nl *ItemList) NodeDelete(node *skiplist.SkipListElementReference) error {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
return nl.client.Del(context.Background(), key).Err()
|
||||
}
|
||||
|
||||
func (nl *ItemList) NodeInnerPosition(node *skiplist.SkipListElementReference, name string) int {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
return int(nl.client.ZLexCount(context.Background(), key, "-", "("+name).Val())
|
||||
}
|
||||
|
||||
func (nl *ItemList) NodeMin(node *skiplist.SkipListElementReference) string {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
slice := nl.client.ZRangeByLex(context.Background(), key, &redis.ZRangeBy{
|
||||
Min: "-",
|
||||
Max: "+",
|
||||
Offset: 0,
|
||||
Count: 1,
|
||||
}).Val()
|
||||
if len(slice) > 0 {
|
||||
s := slice[0]
|
||||
return s
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (nl *ItemList) NodeScanInclusiveAfter(node *skiplist.SkipListElementReference, startFrom string, visitNamesFn func(name string) bool) bool {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
if startFrom == "" {
|
||||
startFrom = "-"
|
||||
} else {
|
||||
startFrom = "[" + startFrom
|
||||
}
|
||||
names := nl.client.ZRangeByLex(context.Background(), key, &redis.ZRangeBy{
|
||||
Min: startFrom,
|
||||
Max: "+",
|
||||
}).Val()
|
||||
for _, n := range names {
|
||||
if !visitNamesFn(n) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (nl *ItemList) NodeRangeBeforeExclusive(node *skiplist.SkipListElementReference, stopAt string) ([]string, error) {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
if stopAt == "" {
|
||||
stopAt = "+"
|
||||
} else {
|
||||
stopAt = "(" + stopAt
|
||||
}
|
||||
return nl.client.ZRangeByLex(context.Background(), key, &redis.ZRangeBy{
|
||||
Min: "-",
|
||||
Max: stopAt,
|
||||
}).Result()
|
||||
}
|
||||
func (nl *ItemList) NodeRangeAfterExclusive(node *skiplist.SkipListElementReference, startFrom string) ([]string, error) {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
if startFrom == "" {
|
||||
startFrom = "-"
|
||||
} else {
|
||||
startFrom = "(" + startFrom
|
||||
}
|
||||
return nl.client.ZRangeByLex(context.Background(), key, &redis.ZRangeBy{
|
||||
Min: startFrom,
|
||||
Max: "+",
|
||||
}).Result()
|
||||
}
|
||||
|
||||
func (nl *ItemList) NodeDeleteBeforeExclusive(node *skiplist.SkipListElementReference, stopAt string) error {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
if stopAt == "" {
|
||||
stopAt = "+"
|
||||
} else {
|
||||
stopAt = "(" + stopAt
|
||||
}
|
||||
return nl.client.ZRemRangeByLex(context.Background(), key, "-", stopAt).Err()
|
||||
}
|
||||
func (nl *ItemList) NodeDeleteAfterExclusive(node *skiplist.SkipListElementReference, startFrom string) error {
|
||||
key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
|
||||
if startFrom == "" {
|
||||
startFrom = "-"
|
||||
} else {
|
||||
startFrom = "(" + startFrom
|
||||
}
|
||||
return nl.client.ZRemRangeByLex(context.Background(), key, startFrom, "+").Err()
|
||||
}
|
||||
|
||||
func (nl *ItemList) ItemAdd(lookupKey []byte, idIfKnown int64, names ...string) error {
|
||||
if id, err := nl.skipList.InsertByKey(lookupKey, idIfKnown, nil); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if len(names) > 0 {
|
||||
return nl.NodeAddMember(&skiplist.SkipListElementReference{
|
||||
ElementPointer: id,
|
||||
Key: lookupKey,
|
||||
}, names...)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user