* fix multipart etag
* address comments
* clean up
* clean up
* optimization
* address comments
* unquoted etag
* dedup
* upgrade
* clean
* etag
* return quoted tag
* quoted etag
* debug
* s3api: unify ETag retrieval and quoting across handlers
Refactor newListEntry to take *S3ApiServer and use getObjectETag,
and update setResponseHeaders to use the same logic. This ensures
consistent ETags are returned for both listing and direct access.
* s3api: implement ListObjects deduplication for versioned buckets
Handle duplicate entries between the main path and the .versions
directory by prioritizing the latest version when bucket versioning
is enabled.
* s3api: cleanup stale main file entries during versioned uploads
Add explicit deletion of pre-existing "main" files when creating new
versions in versioned buckets. This prevents stale entries from
appearing in bucket listings and ensures consistency.
* s3api: fix cleanup code placement in versioned uploads
Correct the placement of rm calls in completeMultipartUpload and
putVersionedObject to ensure stale main files are properly deleted
during versioned uploads.
* s3api: improve getObjectETag fallback for empty ExtETagKey
Ensure that when ExtETagKey exists but contains an empty value,
the function falls through to MD5/chunk-based calculation instead
of returning an empty string.
* s3api: fix test files for new newListEntry signature
Update test files to use the new newListEntry signature where the
first parameter is *S3ApiServer. Created mockS3ApiServer to properly
test owner display name lookup functionality.
* s3api: use filer.ETag for consistent Md5 handling in getEtagFromEntry
Change getEtagFromEntry fallback to use filer.ETag(entry) instead of
filer.ETagChunks to ensure legacy entries with Attributes.Md5 are
handled consistently with the rest of the codebase.
* s3api: optimize list logic and fix conditional header logging
- Hoist bucket versioning check out of per-entry callback to avoid
repeated getVersioningState calls
- Extract appendOrDedup helper function to eliminate duplicate
dedup/append logic across multiple code paths
- Change If-Match mismatch logging from glog.Errorf to glog.V(3).Infof
and remove DEBUG prefix for consistency
* s3api: fix test mock to properly initialize IAM accounts
Fixed nil pointer dereference in TestNewListEntryOwnerDisplayName by
directly initializing the IdentityAccessManagement.accounts map in the
test setup. This ensures newListEntry can properly look up account
display names without panicking.
* cleanup
* s3api: remove premature main file cleanup in versioned uploads
Removed incorrect cleanup logic that was deleting main files during
versioned uploads. This was causing test failures because it deleted
objects that should have been preserved as null versions when
versioning was first enabled. The deduplication logic in listing is
sufficient to handle duplicate entries without deleting files during
upload.
* s3api: add empty-value guard to getEtagFromEntry
Added the same empty-value guard used in getObjectETag to prevent
returning quoted empty strings. When ExtETagKey exists but is empty,
the function now falls through to filer.ETag calculation instead of
returning "".
* s3api: fix listing of directory key objects with matching prefix
Revert prefix handling logic to use strings.TrimPrefix instead of
checking HasPrefix with empty string result. This ensures that when a
directory key object exactly matches the prefix (e.g. prefix="dir/",
object="dir/"), it is correctly handled as a regular entry instead of
being skipped or incorrectly processed as a common prefix. Also fixed
missing variable definition.
* s3api: refactor list inline dedup to use appendOrDedup helper
Refactored the inline deduplication logic in listFilerEntries to use the
shared appendOrDedup helper function. This ensures consistent behavior
and reduces code duplication.
* test: fix port allocation race in s3tables integration test
Updated startMiniCluster to find all required ports simultaneously using
findAvailablePorts instead of sequentially. This prevents race conditions
where the OS reallocates a port that was just released, causing multiple
services (e.g. Filer and Volume) to be assigned the same port and fail
to start.
This document describes the binary layout of the Needle structure as used in SeaweedFS storage, for all supported versions (v1, v2, v3).
A Needle represents a file or data blob stored in a volume file. The layout determines how the Needle is serialized to disk for efficient storage and retrieval.
Common Field Sizes
Field
Size (bytes)
Cookie
4
NeedleId
8
Size
4
DataSize
4
Flags
1
NameSize
1
MimeSize
1
LastModified
5
Ttl
2
PairsSize
2
Checksum
4
Timestamp
8
Needle Layouts by Version
Version 1
Offset
Field
Size (bytes)
Description
0
Cookie
4
Random number to mitigate brute force lookups
4
Id
8
Needle ID
12
Size
4
Length of Data
16
Data
N
File data (N = Size)
16+N
Checksum
4
CRC32 of Data
20+N
Padding
0-7
To align to 8 bytes
Version 2
Offset
Field
Size (bytes)
Description
0
Cookie
4
Random number
4
Id
8
Needle ID
12
Size
4
Total size of the following fields
16
DataSize
4
Length of Data (N)
20
Data
N
File data
20+N
Flags
1
Bit flags
21+N
NameSize
1 (opt)
Optional, if present
22+N
Name
M (opt)
Optional, if present (M = NameSize)
...
MimeSize
1 (opt)
Optional, if present
...
Mime
K (opt)
Optional, if present (K = MimeSize)
...
LastModified
5 (opt)
Optional, if present
...
Ttl
2 (opt)
Optional, if present
...
PairsSize
2 (opt)
Optional, if present
...
Pairs
P (opt)
Optional, if present (P = PairsSize)
...
Checksum
4
CRC32
...
Padding
0-7
To align to 8 bytes
Version 3
Offset
Field
Size (bytes)
Description
0
Cookie
4
Random number
4
Id
8
Needle ID
12
Size
4
Total size of the following fields
16
DataSize
4
Length of Data (N)
20
Data
N
File data
20+N
Flags
1
Bit flags
21+N
NameSize
1 (opt)
Optional, if present
22+N
Name
M (opt)
Optional, if present (M = NameSize)
...
MimeSize
1 (opt)
Optional, if present
...
Mime
K (opt)
Optional, if present (K = MimeSize)
...
LastModified
5 (opt)
Optional, if present
...
Ttl
2 (opt)
Optional, if present
...
PairsSize
2 (opt)
Optional, if present
...
Pairs
P (opt)
Optional, if present (P = PairsSize)
...
Checksum
4
CRC32
...
Timestamp
8
Append time in nanoseconds
...
Padding
0-7
To align to 8 bytes
Offsets marked with ... depend on the presence and size of previous optional fields.
Fields marked (opt) are optional and only present if the corresponding size or flag is non-zero.
N = DataSize, M = NameSize, K = MimeSize, P = PairsSize.
Field Explanations
Cookie: 4 bytes, random value for security.
Id: 8 bytes, unique identifier for the Needle.
Size: 4 bytes, total size of the Needle data section (not including header, checksum, timestamp, or padding).
Checksum: 4 bytes, CRC32 checksum of the Needle data.
Timestamp: 8 bytes, append time (only in v3).
Padding: 0-7 bytes, to align the total Needle size to 8 bytes.
Version Comparison Table
Field
v1
v2
v3
Cookie
✔
✔
✔
Id
✔
✔
✔
Size
✔
✔
✔
DataSize
✔
✔
Data
✔
✔
✔
Flags
✔
✔
NameSize/Name
✔
✔
MimeSize/Mime
✔
✔
LastModified
✔
✔
Ttl
✔
✔
PairsSize/Pairs
✔
✔
Checksum
✔
✔
✔
Timestamp
✔
Padding
✔
✔
✔
Flags Field Details
The Flags field (present in v2 and v3) is a bitmask that encodes several boolean properties of the Needle. Each bit has a specific meaning:
Bit Value
Name
Meaning
0x01
FlagIsCompressed
Data is compressed (isCompressed)
0x02
FlagHasName
Name field is present (NameSize/Name)
0x04
FlagHasMime
Mime field is present (MimeSize/Mime)
0x08
FlagHasLastModifiedDate
LastModified field is present
0x10
FlagHasTtl
Ttl field is present
0x20
FlagHasPairs
Pairs field is present (PairsSize/Pairs)
0x80
FlagIsChunkManifest
Data is a chunk manifest (for large files)
If a flag is set, the corresponding field(s) will appear in the Needle layout at the appropriate position.
The Flags field is always present in v2 and v3, immediately after the Data field.
Optional Fields
Fields marked as optional in the layout tables are only present if the corresponding flag in the Flags field is set (except for Name/Mime/Pairs, which also depend on their size fields being non-zero).
The order of optional fields is fixed and matches the order of their flags.
Special Notes
isCompressed: If set, the Data field is compressed (typically using gzip). This is indicated by the lowest bit (0x01) in the Flags byte.
isChunkManifest: If set, the Data field contains a manifest describing chunks of a large file, not raw file data.
All multi-byte fields are stored in big-endian order.
Padding is always added at the end to align the total Needle size to 8 bytes.
N = DataSize, M = NameSize, K = MimeSize, P = PairsSize in the layout tables above.
For more details, see the implementation in the corresponding Go files in this directory.