diff --git a/weed/filer/foundationdb/foundationdb_store.go b/weed/filer/foundationdb/foundationdb_store.go index 23f53c3e0..0482dc97e 100644 --- a/weed/filer/foundationdb/foundationdb_store.go +++ b/weed/filer/foundationdb/foundationdb_store.go @@ -4,7 +4,6 @@ package foundationdb import ( - "bytes" "context" "fmt" "strings" @@ -25,37 +24,6 @@ const ( FDB_TRANSACTION_SIZE_LIMIT = 10 * 1024 * 1024 ) -// Helper function to create prefix range (tries idiomatic approach first, falls back to custom) -func prefixRange(prefix fdb.Key) fdb.KeyRange { - // Try to use idiomatic FoundationDB PrefixRange if available - // Note: This may not be available in older Go bindings, so we provide fallback - begin := prefix - end := prefixEndFallback(prefix) - return fdb.KeyRange{Begin: begin, End: end} -} - -// Fallback implementation for prefix end calculation -func prefixEndFallback(prefix fdb.Key) fdb.Key { - if len(prefix) == 0 { - return fdb.Key("\xff") - } - - // Create a copy and increment the last byte - end := make([]byte, len(prefix)) - copy(end, prefix) - - // Find the last byte that can be incremented - for i := len(end) - 1; i >= 0; i-- { - if end[i] < 0xff { - end[i]++ - return fdb.Key(end[:i+1]) - } - } - - // All bytes are 0xff, append 0x00 - return fdb.Key(append(end, 0x00)) -} - func init() { filer.Stores = append(filer.Stores, &FoundationDBStore{}) } @@ -297,18 +265,22 @@ func (store *FoundationDBStore) DeleteEntry(ctx context.Context, fullpath util.F } func (store *FoundationDBStore) DeleteFolderChildren(ctx context.Context, fullpath util.FullPath) error { - directoryPrefix := store.genDirectoryKeyPrefix(string(fullpath), "") + // Construct tuple-aware range for all children in this directory + // Use FDBRangeKeys for proper tuple-encoded range + beginKey, endKey := tuple.Tuple{string(fullpath)}.FDBRangeKeys() + // Pack with directory subspace + startKey := store.seaweedfsDir.Pack(beginKey) + endKeyPacked := store.seaweedfsDir.Pack(endKey) + kr := fdb.KeyRange{Begin: startKey, End: endKeyPacked} // Check if there's a transaction in context if tx, exists := store.getTransactionFromContext(ctx); exists { - kr := prefixRange(directoryPrefix) tx.ClearRange(kr) return nil } // Execute in a new transaction if not in an existing one _, err := store.database.Transact(func(tr fdb.Transaction) (interface{}, error) { - kr := prefixRange(directoryPrefix) tr.ClearRange(kr) return nil, nil }) @@ -329,30 +301,37 @@ func (store *FoundationDBStore) ListDirectoryPrefixedEntries(ctx context.Context limit = 1000 } - // Construct tight range based on directory and prefix - directoryPrefix := store.genDirectoryKeyPrefix(string(dirPath), prefix) - - // Determine the actual start key + // For tuple-encoded keys, construct range using directory tuples var startKey fdb.Key + var endKey fdb.Key + + // Determine start key based on startFileName and prefix if startFileName != "" { - // Start from the specified file within the prefix range - startKey = store.genDirectoryKeyPrefix(string(dirPath), startFileName) + // Start from the specified file + startKey = store.seaweedfsDir.Pack(tuple.Tuple{string(dirPath), startFileName}) if !includeStartFile { + // Append 0x00 to exclude the start key itself startKey = append(startKey, 0x00) } - // Ensure startKey is within the prefix range - if !bytes.HasPrefix(startKey, directoryPrefix) { - // If startFileName is before the prefix, start at prefix - if bytes.Compare(startKey, directoryPrefix) < 0 { - startKey = directoryPrefix + // If prefix is specified and startFileName doesn't match, adjust + if prefix != "" && !strings.HasPrefix(startFileName, prefix) { + if startFileName < prefix { + // Start from prefix if startFileName is before it + startKey = store.seaweedfsDir.Pack(tuple.Tuple{string(dirPath), prefix}) } } + } else if prefix != "" { + // Start from prefix + startKey = store.seaweedfsDir.Pack(tuple.Tuple{string(dirPath), prefix}) } else { - startKey = directoryPrefix + // Start from beginning of directory + startKey = store.seaweedfsDir.Pack(tuple.Tuple{string(dirPath), ""}) } - // End key is the prefix range end - endKey := prefixEndFallback(directoryPrefix) + // Compute the end key using tuple-aware range + // This ensures we stay within the directory bounds + beginTuple, endTuple := tuple.Tuple{string(dirPath)}.FDBRangeKeys() + endKey = store.seaweedfsDir.Pack(endTuple) var kvs []fdb.KeyValue var rangeErr error @@ -385,8 +364,9 @@ func (store *FoundationDBStore) ListDirectoryPrefixedEntries(ctx context.Context continue } - // Prefix filtering is now handled by the range scan, but double-check for safety + // Filter by prefix if specified if prefix != "" && !strings.HasPrefix(fileName, prefix) { + glog.V(2).Infof("list %s: fileName %s does not match prefix %s", dirPath, fileName, prefix) continue }