Browse Source

apply the patch

pull/7178/head
chrislu 4 weeks ago
parent
commit
369c7e048a
  1. 20
      test/foundationdb/Dockerfile.build
  2. 177
      test/foundationdb/docker-compose.yml
  3. 2
      test/foundationdb/foundationdb_concurrent_test.go
  4. 2
      test/foundationdb/foundationdb_integration_test.go
  5. 2
      test/foundationdb/test_fdb_s3.sh
  6. 4
      test/foundationdb/wait_for_services.sh
  7. 8
      weed/filer/foundationdb/foundationdb_store.go
  8. 13
      weed/filer/foundationdb/foundationdb_store_test.go

20
test/foundationdb/Dockerfile.build

@ -2,6 +2,9 @@
# Force x86_64 platform to use AMD64 FoundationDB packages # Force x86_64 platform to use AMD64 FoundationDB packages
FROM --platform=linux/amd64 golang:1.24-bookworm FROM --platform=linux/amd64 golang:1.24-bookworm
ARG FOUNDATIONDB_VERSION=7.4.5
ENV FOUNDATIONDB_VERSION=${FOUNDATIONDB_VERSION}
# Install system dependencies and FoundationDB # Install system dependencies and FoundationDB
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
build-essential \ build-essential \
@ -11,9 +14,9 @@ RUN apt-get update && apt-get install -y \
# Install FoundationDB client libraries (x86_64 emulation) # Install FoundationDB client libraries (x86_64 emulation)
RUN echo "🏗️ Installing FoundationDB AMD64 package with x86_64 emulation..." \ RUN echo "🏗️ Installing FoundationDB AMD64 package with x86_64 emulation..." \
&& wget -q https://github.com/apple/foundationdb/releases/download/7.1.61/foundationdb-clients_7.1.61-1_amd64.deb \
&& dpkg -i foundationdb-clients_7.1.61-1_amd64.deb \
&& rm foundationdb-clients_7.1.61-1_amd64.deb \
&& wget -q https://github.com/apple/foundationdb/releases/download/${FOUNDATIONDB_VERSION}/foundationdb-clients_${FOUNDATIONDB_VERSION}-1_amd64.deb \
&& dpkg -i foundationdb-clients_${FOUNDATIONDB_VERSION}-1_amd64.deb \
&& rm foundationdb-clients_${FOUNDATIONDB_VERSION}-1_amd64.deb \
&& echo "🔍 Verifying FoundationDB installation..." \ && echo "🔍 Verifying FoundationDB installation..." \
&& ls -la /usr/include/foundationdb/ \ && ls -la /usr/include/foundationdb/ \
&& ls -la /usr/lib/*/libfdb_c* 2>/dev/null || echo "Library files:" \ && ls -la /usr/lib/*/libfdb_c* 2>/dev/null || echo "Library files:" \
@ -23,7 +26,7 @@ RUN echo "🏗️ Installing FoundationDB AMD64 package with x86_64 emulation...
# Set up Go environment for CGO # Set up Go environment for CGO
ENV CGO_ENABLED=1 ENV CGO_ENABLED=1
ENV GOOS=linux ENV GOOS=linux
ENV CGO_CFLAGS="-I/usr/include/foundationdb -I/usr/local/include/foundationdb -DFDB_API_VERSION=630"
ENV CGO_CFLAGS="-I/usr/include/foundationdb -I/usr/local/include/foundationdb -DFDB_USE_LATEST_API_VERSION"
ENV CGO_LDFLAGS="-L/usr/lib -lfdb_c" ENV CGO_LDFLAGS="-L/usr/lib -lfdb_c"
# Create work directory # Create work directory
@ -34,6 +37,9 @@ COPY . .
# Using Go 1.24 to match project requirements # Using Go 1.24 to match project requirements
# Download foundationdb binding
RUN go get github.com/apple/foundationdb/bindings/go@${FOUNDATIONDB_VERSION}
# Download dependencies (using versions from go.mod for deterministic builds) # Download dependencies (using versions from go.mod for deterministic builds)
RUN go mod download RUN go mod download
@ -46,9 +52,9 @@ RUN echo "🔨 Building SeaweedFS with FoundationDB support..." && \
echo "CGO_CFLAGS: $CGO_CFLAGS" && \ echo "CGO_CFLAGS: $CGO_CFLAGS" && \
echo "CGO_LDFLAGS: $CGO_LDFLAGS" && \ echo "CGO_LDFLAGS: $CGO_LDFLAGS" && \
go build -tags foundationdb -ldflags="-w -s" -o weed ./weed && \ go build -tags foundationdb -ldflags="-w -s" -o weed ./weed && \
chmod +x weed && \
chmod +x ./weed/weed && \
echo "✅ Build successful!" && \ echo "✅ Build successful!" && \
./weed version
./weed/weed version
# Test compilation (don't run tests as they need cluster) # Test compilation (don't run tests as they need cluster)
RUN echo "🧪 Compiling tests..." && \ RUN echo "🧪 Compiling tests..." && \
@ -59,7 +65,7 @@ RUN echo "🧪 Compiling tests..." && \
RUN mkdir -p /var/fdb/config /usr/local/bin RUN mkdir -p /var/fdb/config /usr/local/bin
# Copy binaries to final location # Copy binaries to final location
RUN cp weed /usr/local/bin/weed && \
RUN cp weed/weed /usr/local/bin/weed && \
cp fdb_store_test /usr/local/bin/fdb_store_test cp fdb_store_test /usr/local/bin/fdb_store_test
# Default command # Default command

177
test/foundationdb/docker-compose.yml

@ -1,111 +1,83 @@
version: '3.9'
services: services:
# FoundationDB cluster nodes
fdb1: fdb1:
image: foundationdb/foundationdb:7.1.61
platform: linux/amd64
image: $FOUNDATIONDB_IMAGE
environment: environment:
- FDB_NETWORKING_MODE=host
- FDB_COORDINATOR_PORT=4500
- FDB_PORT=4501
ports:
- "4500:4500"
- "4501:4501"
volumes:
- fdb1_data:/var/fdb/data
- fdb_config:/var/fdb/config
- FDB_CLUSTER_FILE_CONTENTS
- FDB_NETWORKING_MODE=container
- FDB_COORDINATOR_PORT=$FDB_PORT
- FDB_PORT=$FDB_PORT
networks: networks:
- fdb_network - fdb_network
command: |
bash -c "
# Initialize cluster configuration
if [ ! -f /var/fdb/config/fdb.cluster ]; then
echo 'testing:testing@fdb1:4500,fdb2:4500,fdb3:4500' > /var/fdb/config/fdb.cluster
fi
# Start FDB processes
/usr/bin/fdbserver --config_path=/var/fdb/config --datadir=/var/fdb/data --logdir=/var/fdb/logs --public_address=fdb1:4501 --listen_address=0.0.0.0:4501 --coordination=fdb1:4500 &
/usr/bin/fdbserver --config_path=/var/fdb/config --datadir=/var/fdb/data --logdir=/var/fdb/logs --public_address=fdb1:4500 --listen_address=0.0.0.0:4500 --coordination=fdb1:4500 --class=coordination &
wait
"
healthcheck:
test: [ "CMD", "nc", "-z", "127.0.0.1", "4500" ]
interval: 5s
timeout: 5s
retries: 60
fdb2: fdb2:
image: foundationdb/foundationdb:7.1.61
platform: linux/amd64
image: $FOUNDATIONDB_IMAGE
environment: environment:
- FDB_NETWORKING_MODE=host
- FDB_COORDINATOR_PORT=4502
- FDB_PORT=4503
ports:
- "4502:4502"
- "4503:4503"
volumes:
- fdb2_data:/var/fdb/data
- fdb_config:/var/fdb/config
- FDB_CLUSTER_FILE_CONTENTS
- FDB_NETWORKING_MODE=container
- FDB_COORDINATOR_PORT=$FDB_PORT
- FDB_PORT=$FDB_PORT
networks: networks:
- fdb_network - fdb_network
depends_on:
- fdb1
command: |
bash -c "
# Wait for cluster file from fdb1
while [ ! -f /var/fdb/config/fdb.cluster ]; do sleep 1; done
# Start FDB processes
/usr/bin/fdbserver --config_path=/var/fdb/config --datadir=/var/fdb/data --logdir=/var/fdb/logs --public_address=fdb2:4503 --listen_address=0.0.0.0:4503 --coordination=fdb1:4500 &
/usr/bin/fdbserver --config_path=/var/fdb/config --datadir=/var/fdb/data --logdir=/var/fdb/logs --public_address=fdb2:4502 --listen_address=0.0.0.0:4502 --coordination=fdb1:4500 --class=coordination &
wait
"
healthcheck:
test: [ "CMD", "nc", "-z", "127.0.0.1", "4500" ]
interval: 5s
timeout: 5s
retries: 60
fdb3: fdb3:
image: foundationdb/foundationdb:7.1.61
platform: linux/amd64
image: $FOUNDATIONDB_IMAGE
environment: environment:
- FDB_NETWORKING_MODE=host
- FDB_COORDINATOR_PORT=4504
- FDB_PORT=4505
ports:
- "4504:4504"
- "4505:4505"
volumes:
- fdb3_data:/var/fdb/data
- fdb_config:/var/fdb/config
- FDB_CLUSTER_FILE_CONTENTS
- FDB_NETWORKING_MODE=container
- FDB_COORDINATOR_PORT=$FDB_PORT
- FDB_PORT=$FDB_PORT
networks: networks:
- fdb_network - fdb_network
depends_on:
- fdb1
command: |
bash -c "
# Wait for cluster file from fdb1
while [ ! -f /var/fdb/config/fdb.cluster ]; do sleep 1; done
# Start FDB processes
/usr/bin/fdbserver --config_path=/var/fdb/config --datadir=/var/fdb/data --logdir=/var/fdb/logs --public_address=fdb3:4505 --listen_address=0.0.0.0:4505 --coordination=fdb1:4500 &
/usr/bin/fdbserver --config_path=/var/fdb/config --datadir=/var/fdb/data --logdir=/var/fdb/logs --public_address=fdb3:4504 --listen_address=0.0.0.0:4504 --coordination=fdb1:4500 --class=coordination &
wait
"
healthcheck:
test: [ "CMD", "nc", "-z", "127.0.0.1", "4500" ]
interval: 5s
timeout: 5s
retries: 60
# Initialize and configure the database # Initialize and configure the database
fdb-init: fdb-init:
image: foundationdb/foundationdb:7.1.61
image: $FOUNDATIONDB_IMAGE
platform: linux/amd64 platform: linux/amd64
volumes:
- fdb_config:/var/fdb/config
configs:
- target: /var/fdb/config/fdb.cluster
source: fdb.cluster
environment:
- FDB_CLUSTER_FILE=/var/fdb/config/fdb.cluster
networks: networks:
- fdb_network - fdb_network
depends_on: depends_on:
- fdb1
- fdb2
- fdb3
command: |
fdb1:
condition: service_healthy
fdb2:
condition: service_healthy
fdb3:
condition: service_healthy
entrypoint: |
bash -c " bash -c "
# Wait for cluster file
while [ ! -f /var/fdb/config/fdb.cluster ]; do sleep 1; done
set -o errexit
# Wait for cluster to be ready # Wait for cluster to be ready
sleep 10 sleep 10
# Configure database # Configure database
echo 'Initializing FoundationDB database...' echo 'Initializing FoundationDB database...'
fdbcli --exec 'configure new single ssd'
if ! fdbcli --exec 'configure new single ssd' >/tmp/fdbcli.out 2>&1; then
if ! grep -qi 'ERROR: Database already exists!' /tmp/fdbcli.out >/dev/null 2>/dev/null; then
echo 'ERROR: Database initialization failed!' >&2
cat /tmp/fdbcli.out >&2
exit 1
fi
fi
# Wait for configuration to complete # Wait for configuration to complete
sleep 5 sleep 5
@ -114,44 +86,43 @@ services:
fdbcli --exec 'status' fdbcli --exec 'status'
echo 'FoundationDB cluster initialization complete!' echo 'FoundationDB cluster initialization complete!'
# Keep container running for debugging if needed
tail -f /dev/null
" "
# SeaweedFS service with FoundationDB filer # SeaweedFS service with FoundationDB filer
seaweedfs: seaweedfs:
image: chrislusf/seaweedfs:local
image: $SEAWEEDFS_IMAGE
depends_on:
fdb-init:
condition: service_completed_successfully
networks:
- fdb_network
ports: ports:
- "9333:9333" - "9333:9333"
- "19333:19333" - "19333:19333"
- "8888:8888" - "8888:8888"
- "8333:8333" - "8333:8333"
- "18888:18888" - "18888:18888"
command: "server -ip=seaweedfs -filer -master.volumeSizeLimitMB=16 -volume.max=0 -volume -volume.preStopSeconds=1 -s3 -s3.config=/etc/seaweedfs/s3.json -s3.port=8333 -s3.allowEmptyFolder=false -s3.allowDeleteBucketNotEmpty=false"
configs:
- target: /var/fdb/config/fdb.cluster
source: fdb.cluster
volumes: volumes:
- ./s3.json:/etc/seaweedfs/s3.json - ./s3.json:/etc/seaweedfs/s3.json
- ./filer.toml:/etc/seaweedfs/filer.toml - ./filer.toml:/etc/seaweedfs/filer.toml
- fdb_config:/var/fdb/config
environment: environment:
WEED_LEVELDB2_ENABLED: "false"
WEED_FOUNDATIONDB_ENABLED: "true"
WEED_FOUNDATIONDB_CLUSTER_FILE: "/var/fdb/config/fdb.cluster"
WEED_FOUNDATIONDB_API_VERSION: "720"
WEED_FOUNDATIONDB_TIMEOUT: "5s"
WEED_FOUNDATIONDB_MAX_RETRY_DELAY: "1s"
WEED_MASTER_VOLUME_GROWTH_COPY_1: 1
WEED_MASTER_VOLUME_GROWTH_COPY_OTHER: 1
networks:
- fdb_network
depends_on:
- fdb-init
- WEED_LEVELDB2_ENABLED
- WEED_FOUNDATIONDB_ENABLED
- WEED_FOUNDATIONDB_CLUSTER_FILE
- WEED_FOUNDATIONDB_API_VERSION
- WEED_FOUNDATIONDB_TIMEOUT
- WEED_FOUNDATIONDB_MAX_RETRY_DELAY
- WEED_MASTER_VOLUME_GROWTH_COPY_1=1
- WEED_MASTER_VOLUME_GROWTH_COPY_OTHER=1
command: "weed server -ip=seaweedfs -filer -master.volumeSizeLimitMB=16 -volume.max=0 -volume -volume.preStopSeconds=1 -s3 -s3.config=/etc/seaweedfs/s3.json -s3.port=8333 -s3.allowEmptyFolder=false -s3.allowDeleteBucketNotEmpty=false"
volumes:
fdb1_data:
fdb2_data:
fdb3_data:
fdb_config:
configs:
fdb.cluster:
content: |
$FDB_CLUSTER_FILE_CONTENTS
networks: networks:
fdb_network: fdb_network:

2
test/foundationdb/foundationdb_concurrent_test.go

@ -428,7 +428,7 @@ func createTestStore(t *testing.T) *foundationdb.FoundationDBStore {
t.Skip("FoundationDB cluster file not found, skipping test") t.Skip("FoundationDB cluster file not found, skipping test")
} }
config := util.NewViper()
config := util.GetViper()
config.Set("foundationdb.cluster_file", clusterFile) config.Set("foundationdb.cluster_file", clusterFile)
config.Set("foundationdb.api_version", 720) config.Set("foundationdb.api_version", 720)
config.Set("foundationdb.timeout", "10s") config.Set("foundationdb.timeout", "10s")

2
test/foundationdb/foundationdb_integration_test.go

@ -352,7 +352,7 @@ func createTestStore(t *testing.T) *foundationdb.FoundationDBStore {
t.Skip("FoundationDB cluster file not found, skipping test") t.Skip("FoundationDB cluster file not found, skipping test")
} }
config := util.NewViper()
config := util.GetViper()
config.Set("foundationdb.cluster_file", clusterFile) config.Set("foundationdb.cluster_file", clusterFile)
config.Set("foundationdb.api_version", 630) config.Set("foundationdb.api_version", 630)
config.Set("foundationdb.timeout", "10s") config.Set("foundationdb.timeout", "10s")

2
test/foundationdb/test_fdb_s3.sh

@ -97,7 +97,7 @@ fi
echo -e "${BLUE}Test: FoundationDB backend verification${NC}" echo -e "${BLUE}Test: FoundationDB backend verification${NC}"
# Check that data is actually stored in FoundationDB # Check that data is actually stored in FoundationDB
docker-compose exec -T fdb-init fdbcli --exec 'getrange seaweedfs seaweedfs\xFF' > fdb_keys.txt || true
docker-compose exec -T fdb1 fdbcli --exec 'getrange seaweedfs seaweedfs\xFF' > fdb_keys.txt || true
if [ -s fdb_keys.txt ] && grep -q "seaweedfs" fdb_keys.txt; then if [ -s fdb_keys.txt ] && grep -q "seaweedfs" fdb_keys.txt; then
echo -e "${GREEN}✅ Data confirmed in FoundationDB backend${NC}" echo -e "${GREEN}✅ Data confirmed in FoundationDB backend${NC}"

4
test/foundationdb/wait_for_services.sh

@ -17,7 +17,7 @@ MAX_ATTEMPTS=30
ATTEMPT=0 ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
if docker-compose exec -T fdb-init fdbcli --exec 'status' > /dev/null 2>&1; then
if docker-compose exec -T fdb1 fdbcli --exec 'status' > /dev/null 2>&1; then
echo -e "${GREEN}✅ FoundationDB cluster is ready${NC}" echo -e "${GREEN}✅ FoundationDB cluster is ready${NC}"
break break
fi fi
@ -103,7 +103,7 @@ echo -e "${GREEN}🎉 All services are ready!${NC}"
# Display final status # Display final status
echo -e "${BLUE}Final status check:${NC}" echo -e "${BLUE}Final status check:${NC}"
docker-compose exec -T fdb-init fdbcli --exec 'status'
docker-compose exec -T fdb1 fdbcli --exec 'status'
echo "" echo ""
echo -e "${BLUE}SeaweedFS cluster info:${NC}" echo -e "${BLUE}SeaweedFS cluster info:${NC}"
curl -s http://127.0.0.1:9333/cluster/status | head -20 curl -s http://127.0.0.1:9333/cluster/status | head -20

8
weed/filer/foundationdb/foundationdb_store.go

@ -63,7 +63,6 @@ func init() {
type FoundationDBStore struct { type FoundationDBStore struct {
database fdb.Database database fdb.Database
dirLayer directory.Directory
seaweedfsDir directory.DirectorySubspace seaweedfsDir directory.DirectorySubspace
kvDir directory.DirectorySubspace kvDir directory.DirectorySubspace
directoryPrefix string directoryPrefix string
@ -135,17 +134,14 @@ func (store *FoundationDBStore) initialize(clusterFile string, apiVersion int) e
return fmt.Errorf("failed to open FoundationDB database: %v", err) return fmt.Errorf("failed to open FoundationDB database: %v", err)
} }
// Create directory layer
store.dirLayer = directory.NewDirectoryLayer(subspace.Sub(), subspace.Sub(), false)
// Create/open seaweedfs directory // Create/open seaweedfs directory
store.seaweedfsDir, err = store.dirLayer.CreateOrOpen(store.database, []string{store.directoryPrefix}, nil)
store.seaweedfsDir, err = directory.CreateOrOpen(store.database, []string{store.directoryPrefix, "data"}, nil)
if err != nil { if err != nil {
return fmt.Errorf("failed to create/open seaweedfs directory: %v", err) return fmt.Errorf("failed to create/open seaweedfs directory: %v", err)
} }
// Create/open kv subdirectory for key-value operations // Create/open kv subdirectory for key-value operations
store.kvDir, err = store.dirLayer.CreateOrOpen(store.database, []string{store.directoryPrefix, "kv"}, nil)
store.kvDir, err = directory.CreateOrOpen(store.database, []string{store.directoryPrefix, "kv"}, nil)
if err != nil { if err != nil {
return fmt.Errorf("failed to create/open kv directory: %v", err) return fmt.Errorf("failed to create/open kv directory: %v", err)
} }

13
weed/filer/foundationdb/foundationdb_store_test.go

@ -5,6 +5,7 @@ package foundationdb
import ( import (
"context" "context"
"fmt"
"os" "os"
"testing" "testing"
"time" "time"
@ -16,7 +17,7 @@ import (
func TestFoundationDBStore_Initialize(t *testing.T) { func TestFoundationDBStore_Initialize(t *testing.T) {
// Test with default configuration // Test with default configuration
config := util.NewViper()
config := util.GetViper()
config.Set("foundationdb.cluster_file", getTestClusterFile()) config.Set("foundationdb.cluster_file", getTestClusterFile())
config.Set("foundationdb.api_version", 630) config.Set("foundationdb.api_version", 630)
@ -38,7 +39,7 @@ func TestFoundationDBStore_Initialize(t *testing.T) {
} }
func TestFoundationDBStore_InitializeWithCustomConfig(t *testing.T) { func TestFoundationDBStore_InitializeWithCustomConfig(t *testing.T) {
config := util.NewViper()
config := util.GetViper()
config.Set("foundationdb.cluster_file", getTestClusterFile()) config.Set("foundationdb.cluster_file", getTestClusterFile())
config.Set("foundationdb.api_version", 630) config.Set("foundationdb.api_version", 630)
config.Set("foundationdb.timeout", "10s") config.Set("foundationdb.timeout", "10s")
@ -97,7 +98,7 @@ func TestFoundationDBStore_InitializeInvalidConfig(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
config := util.NewViper()
config := util.GetViper()
for key, value := range tt.config { for key, value := range tt.config {
config.Set(key, value) config.Set(key, value)
} }
@ -282,7 +283,7 @@ func BenchmarkFoundationDBStore_InsertEntry(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
entry.FullPath = util.NewFullPath("/benchmark", util.Uint64toHex(uint64(i))+".txt")
entry.FullPath = util.NewFullPath("/benchmark", fmt.Sprintf("%x", uint64(i))+".txt")
err := store.InsertEntry(ctx, entry) err := store.InsertEntry(ctx, entry)
if err != nil { if err != nil {
b.Fatalf("InsertEntry failed: %v", err) b.Fatalf("InsertEntry failed: %v", err)
@ -300,7 +301,7 @@ func BenchmarkFoundationDBStore_FindEntry(b *testing.B) {
numEntries := 1000 numEntries := 1000
for i := 0; i < numEntries; i++ { for i := 0; i < numEntries; i++ {
entry := &filer.Entry{ entry := &filer.Entry{
FullPath: util.NewFullPath("/benchmark", util.Uint64toHex(uint64(i))+".txt"),
FullPath: util.NewFullPath("/benchmark", fmt.Sprintf("%x", uint64(i))+".txt"),
Attr: filer.Attr{ Attr: filer.Attr{
Mode: 0644, Mode: 0644,
Uid: 1000, Uid: 1000,
@ -316,7 +317,7 @@ func BenchmarkFoundationDBStore_FindEntry(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
path := util.NewFullPath("/benchmark", util.Uint64toHex(uint64(i%numEntries))+".txt")
path := util.NewFullPath("/benchmark", fmt.Sprintf("%x", uint64(i%numEntries))+".txt")
_, err := store.FindEntry(ctx, path) _, err := store.FindEntry(ctx, path)
if err != nil { if err != nil {
b.Fatalf("FindEntry failed: %v", err) b.Fatalf("FindEntry failed: %v", err)

Loading…
Cancel
Save