fix: optimize parentDirIsObject by moving isObject to storage layer (#11291)

For objects with `N` prefix depth, this PR reduces `N` such network
operations by converting `CheckFile` into a single bulk operation.

Reduction in chattiness here would allow disks to be utilized more
cleanly, while maintaining the same functionality along with one
extra volume check stat() call is removed.

Update tests to test multiple sets scenario
This commit is contained in:
Harshavardhana
2021-01-18 12:25:22 -08:00
committed by GitHub
parent 3d9000d5b5
commit 3ca6330661
5 changed files with 84 additions and 104 deletions

View File

@@ -28,7 +28,7 @@ func TestErasureParentDirIsObject(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
obj, fsDisks, err := prepareErasure16(ctx)
obj, fsDisks, err := prepareErasureSets32(ctx)
if err != nil {
t.Fatalf("Unable to initialize 'Erasure' object layer.")
}
@@ -45,59 +45,38 @@ func TestErasureParentDirIsObject(t *testing.T) {
if err = obj.MakeBucketWithLocation(GlobalContext, bucketName, BucketOptions{}); err != nil {
t.Fatal(err)
}
objectContent := "12345"
objInfo, err := obj.PutObject(GlobalContext, bucketName, objectName,
_, err = obj.PutObject(GlobalContext, bucketName, objectName,
mustGetPutObjReader(t, bytes.NewReader([]byte(objectContent)), int64(len(objectContent)), "", ""), ObjectOptions{})
if err != nil {
t.Fatal(err)
}
if objInfo.Name != objectName {
t.Fatalf("Unexpected object name returned got %s, expected %s", objInfo.Name, objectName)
}
z := obj.(*erasureServerPools)
xl := z.serverPools[0].sets[0]
testCases := []struct {
parentIsObject bool
objectName string
expectedErr bool
objectName string
}{
// parentIsObject is true if object is available.
{
parentIsObject: true,
objectName: objectName,
expectedErr: true,
objectName: pathJoin(objectName, "parent-is-object"),
},
{
parentIsObject: false,
objectName: "new-dir",
},
{
parentIsObject: false,
objectName: "",
},
{
parentIsObject: false,
objectName: ".",
},
// Should not cause infinite loop.
{
parentIsObject: false,
objectName: SlashSeparator,
},
{
parentIsObject: false,
objectName: "\\",
},
// Should not cause infinite loop with double forward slash.
{
parentIsObject: false,
objectName: "//",
expectedErr: false,
objectName: pathJoin("no-parent", "object"),
},
}
for i, testCase := range testCases {
gotValue := xl.parentDirIsObject(GlobalContext, bucketName, testCase.objectName)
if testCase.parentIsObject != gotValue {
t.Errorf("Test %d: Unexpected value returned got %t, expected %t", i+1, gotValue, testCase.parentIsObject)
}
for _, testCase := range testCases {
t.Run("", func(t *testing.T) {
_, err = obj.PutObject(GlobalContext, bucketName, testCase.objectName,
mustGetPutObjReader(t, bytes.NewReader([]byte(objectContent)), int64(len(objectContent)), "", ""), ObjectOptions{})
if testCase.expectedErr && err == nil {
t.Error("Expected error but got nil")
}
if !testCase.expectedErr && err != nil {
t.Errorf("Expected nil but got %v", err)
}
})
}
}