diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 5d7094d44..7dd8ca3da 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -71,27 +71,27 @@ func stringifyAddress(addr oid.Address) string { return addr.Object().EncodeToString() + "." + addr.Container().EncodeToString() } -func addressFromString(s string) (*oid.Address, error) { - ss := strings.SplitN(s, ".", 2) - if len(ss) != 2 { - return nil, errors.New("invalid address") +func addressFromString(s string) (oid.Address, error) { + i := strings.IndexByte(s, '.') + if i == -1 { + return oid.Address{}, errors.New("invalid address") } var obj oid.ID - if err := obj.DecodeString(ss[0]); err != nil { - return nil, err + if err := obj.DecodeString(s[:i]); err != nil { + return oid.Address{}, err } var cnr cid.ID - if err := cnr.DecodeString(ss[1]); err != nil { - return nil, err + if err := cnr.DecodeString(s[i+1:]); err != nil { + return oid.Address{}, err } var addr oid.Address addr.SetObject(obj) addr.SetContainer(cnr) - return &addr, nil + return addr, nil } // Iterate iterates over all stored objects. @@ -135,7 +135,7 @@ func (t *FSTree) iterate(depth uint64, curPath []string, prm common.IteratePrm) } if prm.LazyHandler != nil { - err = prm.LazyHandler(*addr, func() ([]byte, error) { + err = prm.LazyHandler(addr, func() ([]byte, error) { return os.ReadFile(filepath.Join(curPath...)) }) } else { @@ -147,7 +147,7 @@ func (t *FSTree) iterate(depth uint64, curPath []string, prm common.IteratePrm) if err != nil { if prm.IgnoreErrors { if prm.ErrorHandler != nil { - return prm.ErrorHandler(*addr, err) + return prm.ErrorHandler(addr, err) } continue } @@ -155,7 +155,7 @@ func (t *FSTree) iterate(depth uint64, curPath []string, prm common.IteratePrm) } err = prm.Handler(common.IterationElement{ - Address: *addr, + Address: addr, ObjectData: data, StorageID: []byte{}, }) @@ -172,17 +172,19 @@ func (t *FSTree) iterate(depth uint64, curPath []string, prm common.IteratePrm) func (t *FSTree) treePath(addr oid.Address) string { sAddr := stringifyAddress(addr) - dirs := make([]string, 0, t.Depth+1+1) // 1 for root, 1 for file - dirs = append(dirs, t.RootPath) + var sb strings.Builder + sb.Grow(len(t.RootPath) + len(sAddr) + int(t.Depth) + 1) + sb.WriteString(t.RootPath) for i := 0; uint64(i) < t.Depth; i++ { - dirs = append(dirs, sAddr[:t.DirNameLen]) + sb.WriteRune(filepath.Separator) + sb.WriteString(sAddr[:t.DirNameLen]) sAddr = sAddr[t.DirNameLen:] } - dirs = append(dirs, sAddr) - - return filepath.Join(dirs...) + sb.WriteRune(filepath.Separator) + sb.WriteString(sAddr) + return sb.String() } // Delete removes the object with the specified address from the storage. @@ -191,15 +193,9 @@ func (t *FSTree) Delete(prm common.DeletePrm) (common.DeleteRes, error) { return common.DeleteRes{}, common.ErrReadOnly } - p, err := t.getPath(prm.Address) - if err != nil { - if os.IsNotExist(err) { - err = logicerr.Wrap(apistatus.ObjectNotFound{}) - } - return common.DeleteRes{}, err - } + p := t.treePath(prm.Address) - err = os.Remove(p) + err := os.Remove(p) if err != nil && os.IsNotExist(err) { err = logicerr.Wrap(apistatus.ObjectNotFound{}) } @@ -209,7 +205,9 @@ func (t *FSTree) Delete(prm common.DeletePrm) (common.DeleteRes, error) { // Exists returns the path to the file with object contents if it exists in the storage // and an error otherwise. func (t *FSTree) Exists(prm common.ExistsPrm) (common.ExistsRes, error) { - _, err := t.getPath(prm.Address) + p := t.treePath(prm.Address) + + _, err := os.Stat(p) found := err == nil if os.IsNotExist(err) { err = nil @@ -217,13 +215,6 @@ func (t *FSTree) Exists(prm common.ExistsPrm) (common.ExistsRes, error) { return common.ExistsRes{Exists: found}, err } -func (t *FSTree) getPath(addr oid.Address) (string, error) { - p := t.treePath(addr) - - _, err := os.Stat(p) - return p, err -} - // Put puts an object in the storage. func (t *FSTree) Put(prm common.PutPrm) (common.PutRes, error) { if t.readOnly { diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_test.go b/pkg/local_object_storage/blobstor/fstree/fstree_test.go index 4bfcc0a95..97fd6032a 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_test.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_test.go @@ -12,5 +12,19 @@ func TestAddressToString(t *testing.T) { s := stringifyAddress(addr) actual, err := addressFromString(s) require.NoError(t, err) - require.Equal(t, addr, *actual) + require.Equal(t, addr, actual) +} + +func Benchmark_addressFromString(b *testing.B) { + addr := oidtest.Address() + s := stringifyAddress(addr) + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := addressFromString(s) + if err != nil { + b.Fatalf("benchmark error: %v", err) + } + } }