aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchrislu <chris.lu@gmail.com>2025-06-07 17:18:21 -0700
committerchrislu <chris.lu@gmail.com>2025-06-07 17:18:21 -0700
commitb7427c7d764aadd8bdfd4e781ec79e6792e75f08 (patch)
tree3156ec59df00e4c68e140e38fa960f317dc795cf
parent60f11f651054a22f2bb16520be231f4ba9ba1640 (diff)
downloadseaweedfs-b7427c7d764aadd8bdfd4e781ec79e6792e75f08.tar.xz
seaweedfs-b7427c7d764aadd8bdfd4e781ec79e6792e75f08.zip
adding ReadFromFile with read options
-rw-r--r--weed/storage/needle/needle_read_options.go24
-rw-r--r--weed/storage/needle/needle_read_options_test.go92
2 files changed, 116 insertions, 0 deletions
diff --git a/weed/storage/needle/needle_read_options.go b/weed/storage/needle/needle_read_options.go
new file mode 100644
index 000000000..6ddc2d88e
--- /dev/null
+++ b/weed/storage/needle/needle_read_options.go
@@ -0,0 +1,24 @@
+package needle
+
+import (
+ "github.com/seaweedfs/seaweedfs/weed/storage/backend"
+ . "github.com/seaweedfs/seaweedfs/weed/storage/types"
+)
+
+// NeedleReadOptions specifies which parts of the Needle to read.
+type NeedleReadOptions struct {
+ ReadHeader bool // always true for any read
+ ReadData bool // read the Data field
+ ReadMeta bool // read metadata fields (Name, Mime, LastModified, Ttl, Pairs, etc.)
+}
+
+// ReadFromFile reads the Needle from the backend file according to the specified options.
+// For now, this is equivalent to ReadData (reads everything).
+func (n *Needle) ReadFromFile(r backend.BackendStorageFile, offset int64, size Size, version Version, opts NeedleReadOptions) error {
+ // Always read header and body for now (full read)
+ bytes, err := ReadNeedleBlob(r, offset, size, version)
+ if err != nil {
+ return err
+ }
+ return n.ReadBytes(bytes, offset, size, version)
+}
diff --git a/weed/storage/needle/needle_read_options_test.go b/weed/storage/needle/needle_read_options_test.go
new file mode 100644
index 000000000..e50b77b59
--- /dev/null
+++ b/weed/storage/needle/needle_read_options_test.go
@@ -0,0 +1,92 @@
+package needle
+
+import (
+ "bytes"
+ "io"
+ "reflect"
+ "testing"
+ "time"
+
+ . "github.com/seaweedfs/seaweedfs/weed/storage/types"
+)
+
+type mockBackend struct {
+ data []byte
+}
+
+func (m *mockBackend) ReadAt(p []byte, off int64) (n int, err error) {
+ if int(off) >= len(m.data) {
+ return 0, io.EOF
+ }
+ n = copy(p, m.data[off:])
+ if n < len(p) {
+ return n, io.EOF
+ }
+ return n, nil
+}
+
+func (m *mockBackend) GetStat() (int64, time.Time, error) {
+ return int64(len(m.data)), time.Time{}, nil
+}
+
+func (m *mockBackend) Name() string {
+ return "mock"
+}
+
+func (m *mockBackend) Close() error {
+ return nil
+}
+
+func (m *mockBackend) Sync() error {
+ return nil
+}
+
+func (m *mockBackend) Truncate(size int64) error {
+ m.data = m.data[:size]
+ return nil
+}
+
+func (m *mockBackend) WriteAt(p []byte, off int64) (n int, err error) {
+ return 0, nil
+}
+
+func TestReadFromFile_EquivalenceWithReadData(t *testing.T) {
+ n := &Needle{
+ Cookie: 0x12345678,
+ Id: 0x1122334455667788,
+ Data: []byte("hello world"),
+ Flags: 0xFF,
+ Name: []byte("filename.txt"),
+ Mime: []byte("text/plain"),
+ LastModified: 0x1234567890,
+ Ttl: nil,
+ Pairs: []byte("key=value"),
+ PairsSize: 9,
+ Checksum: 0xCAFEBABE,
+ AppendAtNs: 0xDEADBEEF,
+ }
+ buf := &bytes.Buffer{}
+ _, _, err := writeNeedleV2(n, 0, buf)
+ if err != nil {
+ t.Fatalf("writeNeedleV2 failed: %v", err)
+ }
+ backend := &mockBackend{data: buf.Bytes()}
+ size := Size(len(buf.Bytes()) - NeedleHeaderSize - NeedleChecksumSize - int(PaddingLength(Size(len(buf.Bytes())-NeedleHeaderSize-NeedleChecksumSize), Version2)))
+
+ // Old method
+ nOld := &Needle{}
+ errOld := nOld.ReadData(backend, 0, size, Version2)
+
+ // New method
+ nNew := &Needle{}
+ opts := NeedleReadOptions{ReadHeader: true, ReadData: true, ReadMeta: true}
+ errNew := nNew.ReadFromFile(backend, 0, size, Version2, opts)
+
+ if (errOld != nil) != (errNew != nil) || (errOld != nil && errOld.Error() != errNew.Error()) {
+ t.Errorf("error mismatch: old=%v new=%v", errOld, errNew)
+ }
+
+ if !reflect.DeepEqual(nOld, nNew) {
+ t.Errorf("needle mismatch: old=%+v new=%+v", nOld, nNew)
+ }
+}