github.com/rohankumardubey/proxyfs@v0.0.0-20210108201508-653efa9ab00e/inode/gc_test.go (about)

     1  package inode
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/swiftstack/ProxyFS/swiftclient"
     8  )
     9  
    10  type testObjectLocationStruct struct {
    11  	accountName   string
    12  	containerName string
    13  	objectName    string
    14  }
    15  
    16  func TestEmptySegmentDeletion(t *testing.T) {
    17  	testSetup(t, false)
    18  
    19  	testVolumeHandle, err := FetchVolumeHandle("TestVolume")
    20  	if nil != err {
    21  		t.Fatalf("FetchVolumeHandle(\"TestVolume\") failed: %v", err)
    22  	}
    23  
    24  	volume := testVolumeHandle.(*volumeStruct)
    25  
    26  	ino, err := testVolumeHandle.CreateFile(PosixModePerm, 0, 0)
    27  	if nil != err {
    28  		t.Fatalf("CreateFile() failed: %v", err)
    29  	}
    30  
    31  	// '$$$$$$$$$$$$$$$$'
    32  	ourBytes := []byte{0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24}
    33  
    34  	// repeatedly write and flush to create some log segments
    35  	for i := 0; i < 5; i++ {
    36  		err := testVolumeHandle.Write(ino, uint64(i*16), ourBytes, nil)
    37  		if err != nil {
    38  			t.Fatalf("failed to write: %v", err)
    39  		}
    40  
    41  		err = testVolumeHandle.Flush(ino, false)
    42  		if err != nil {
    43  			t.Fatalf("failed to flush: %v", err)
    44  		}
    45  	}
    46  
    47  	// inspect log segment map
    48  	ourInode, ok, err := volume.fetchInode(ino)
    49  	if nil != err {
    50  		t.Fatalf("fetchInode(ino==0x%016X) failed: %v", ino, err)
    51  	}
    52  	if !ok {
    53  		t.Fatalf("fetchInode(ino==0x%016X) returned !ok", ino)
    54  	}
    55  	segmentNumbers := make([]uint64, 0, 5)
    56  	segmentObjectLocations := make([]testObjectLocationStruct, 0, 5)
    57  	for segmentNumber := range ourInode.LogSegmentMap {
    58  		segmentNumbers = append(segmentNumbers, segmentNumber)
    59  		containerName, objectName, _, getObjectLocationErr := volume.getObjectLocationFromLogSegmentNumber(segmentNumber)
    60  		if nil != getObjectLocationErr {
    61  			t.Fatalf("expected to be able to get log segment 0x%016X", segmentNumber)
    62  		}
    63  		segmentObjectLocations = append(segmentObjectLocations, testObjectLocationStruct{volume.accountName, containerName, objectName})
    64  	}
    65  
    66  	// overwrite it
    67  	err = testVolumeHandle.Write(ino, 0, make([]byte, 16*5), nil)
    68  	if err != nil {
    69  		t.Fatalf("expected to be able to write to inode #%v", ino)
    70  	}
    71  	err = testVolumeHandle.Flush(ino, false)
    72  	if err != nil {
    73  		t.Fatalf("expected to be able to flush inode #%v", ino)
    74  	}
    75  
    76  	// wait for headhunter checkpoint which blocks deletes
    77  	err = volume.headhunterVolumeHandle.DoCheckpoint()
    78  	if nil != err {
    79  		t.Errorf("expected volume.headhunterVolumeHandle.DoCheckpoint() to succeed: got %v", err)
    80  	}
    81  
    82  	// the deletions are async; give them a (literal) second
    83  	time.Sleep(1 * time.Second)
    84  
    85  	for _, deletedSegmentNumber := range segmentNumbers {
    86  		_, getLogSegmentContainerErr := volume.getLogSegmentContainer(deletedSegmentNumber)
    87  		if getLogSegmentContainerErr == nil {
    88  			t.Errorf("expected volume.getLogSegmentContainer() to fail for allegedly-deleted log segment 0x%016X", deletedSegmentNumber)
    89  		}
    90  	}
    91  
    92  	// the headhunter records got deleted, and ...
    93  	for _, segmentObjectLocation := range segmentObjectLocations {
    94  		var objectContentLengthErr error
    95  
    96  		// wait for up to 20 sec for the object to be (async) deleted
    97  		for try := 0; try < 20; try++ {
    98  			_, objectContentLengthErr = swiftclient.ObjectContentLength(segmentObjectLocation.accountName, segmentObjectLocation.containerName, segmentObjectLocation.objectName)
    99  			//t.Logf("verifying object delete for %v/%v try %d err '%v'\n", segmentObjectLocation.containerName, segmentObjectLocation.objectName, try, objectContentLengthErr)
   100  			if objectContentLengthErr != nil {
   101  				break
   102  			}
   103  			time.Sleep(time.Second)
   104  		}
   105  		if objectContentLengthErr == nil {
   106  			t.Errorf("expected ObjectContentLength() to fail for allegedly-deleted log segment object at %s/%s/%s", segmentObjectLocation.accountName, segmentObjectLocation.containerName, segmentObjectLocation.objectName)
   107  		}
   108  	}
   109  	// the underlying log segment objects got deleted!! Yaaay~! ☆✦❤
   110  
   111  	testTeardown(t)
   112  }