Selaa lähdekoodia

fix: Better StorageManagerError handling

Matthias Ladkau 5 vuotta sitten
vanhempi
commit
6989be9b7d

+ 1 - 1
api/v1/blob.go

@@ -468,7 +468,7 @@ func (be *blobEndpoint) HandleGET(w http.ResponseWriter, r *http.Request, resour
 
 		res, err = sm.FetchCached(loc)
 
-		if err == storage.ErrNotInCache {
+		if sme, ok := err.(*storage.StorageManagerError); ok && sme.Type == storage.ErrNotInCache {
 			err = sm.Fetch(loc, &ret)
 		} else if err == nil && res != nil {
 			ret = res.([]byte)

+ 1 - 1
cluster/distributedstorage_test.go

@@ -250,7 +250,7 @@ func TestSimpleDataDistribution(t *testing.T) {
 		return
 	}
 
-	if _, err := sm.FetchCached(5); err != storage.ErrNotInCache {
+	if _, err := sm.FetchCached(5); err.(*storage.StorageManagerError).Type != storage.ErrNotInCache {
 		t.Error("Unexpected response:", err)
 		return
 	}

+ 1 - 1
cluster/distributedstoragemanager.go

@@ -355,7 +355,7 @@ FetchCached is not implemented for a DistributedStorageManager. Only defined to
 the StorageManager interface.
 */
 func (dsm *DistributedStorageManager) FetchCached(loc uint64) (interface{}, error) {
-	return nil, storage.ErrNotInCache
+	return nil, storage.NewStorageManagerError(storage.ErrNotInCache, "", dsm.Name())
 }
 
 /*

+ 4 - 4
graph/util/indexmanager_test.go

@@ -341,11 +341,11 @@ func TestAddRemoveIndexHashEntry(t *testing.T) {
 
 	sm.AccessMap[2] = storage.AccessCacheAndFetchError
 
-	if err := im.addIndexHashEntry("mykey2", "myattr", "testvalue"); err != storage.ErrSlotNotFound {
+	if err := im.addIndexHashEntry("mykey2", "myattr", "testvalue"); err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error(err)
 		return
 	}
-	if err := im.removeIndexHashEntry("mykey2", "myattr", "testvalue"); err != storage.ErrSlotNotFound {
+	if err := im.removeIndexHashEntry("mykey2", "myattr", "testvalue"); err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error(err)
 		return
 	}
@@ -459,12 +459,12 @@ func TestAddRemoveIndexEntry(t *testing.T) {
 
 	sm.AccessMap[2] = storage.AccessCacheAndFetchError
 
-	if res := im.addIndexEntry("mykey2", "myattr", "myword", []uint64{10, 12, 80}); res != storage.ErrSlotNotFound {
+	if res := im.addIndexEntry("mykey2", "myattr", "myword", []uint64{10, 12, 80}); res.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected result:", res)
 		return
 	}
 
-	if res := im.removeIndexEntry("mykey2", "myattr", "myword", []uint64{10, 12, 80}); res != storage.ErrSlotNotFound {
+	if res := im.removeIndexEntry("mykey2", "myattr", "myword", []uint64{10, 12, 80}); res.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected result:", res)
 		return
 	}

+ 1 - 1
hash/htree_test.go

@@ -122,7 +122,7 @@ func TestHTree(t *testing.T) {
 
 	sm.AccessMap[1] = storage.AccessCacheAndFetchError
 
-	if _, err := LoadHTree(sm, page.Location()); err != storage.ErrSlotNotFound {
+	if _, err := LoadHTree(sm, page.Location()); err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected tree load result:", err)
 		return
 	}

+ 8 - 8
hash/htreepage_test.go

@@ -67,11 +67,11 @@ func TestHTreePageFetchExists(t *testing.T) {
 
 	sm.AccessMap[8] = storage.AccessCacheAndFetchError
 
-	if res, err := page.Exists([]byte("testkey4")); res != false || err != storage.ErrSlotNotFound {
+	if res, err := page.Exists([]byte("testkey4")); res != false || err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected exists result:", res, err)
 		return
 	}
-	if res, _, err := page.Get([]byte("testkey4")); res != nil || err != storage.ErrSlotNotFound {
+	if res, _, err := page.Get([]byte("testkey4")); res != nil || err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected get result:", res, err)
 		return
 	}
@@ -105,7 +105,7 @@ func TestHTreePageInsert(t *testing.T) {
 
 	sm.AccessMap[1] = storage.AccessUpdateError
 
-	if _, err := page.Put([]byte("testkey1"), "test1"); err != storage.ErrSlotNotFound {
+	if _, err := page.Put([]byte("testkey1"), "test1"); err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected put result:", err)
 		return
 	}
@@ -120,7 +120,7 @@ func TestHTreePageInsert(t *testing.T) {
 
 	sm.AccessMap[2] = storage.AccessCacheAndFetchError
 
-	if _, err := page.Put([]byte("testkey2"), "test2"); err != storage.ErrSlotNotFound {
+	if _, err := page.Put([]byte("testkey2"), "test2"); err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected put result:", err)
 		return
 	}
@@ -158,7 +158,7 @@ func TestHTreePageInsert(t *testing.T) {
 
 	sm.AccessMap[1] = storage.AccessUpdateError
 
-	if _, err := page.Put([]byte("testkey9"), "test9"); err != storage.ErrSlotNotFound {
+	if _, err := page.Put([]byte("testkey9"), "test9"); err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected put result:", err)
 		return
 	}
@@ -369,7 +369,7 @@ func TestHTreePageRemove(t *testing.T) {
 
 	sm.AccessMap[16] = storage.AccessCacheAndFetchError
 
-	if _, err := page.Remove([]byte("testkey1")); err != storage.ErrSlotNotFound {
+	if _, err := page.Remove([]byte("testkey1")); err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected remove result", res)
 		return
 	}
@@ -378,7 +378,7 @@ func TestHTreePageRemove(t *testing.T) {
 
 	sm.AccessMap[1] = storage.AccessUpdateError
 
-	if _, err := page.Remove([]byte("testkey10")); err != storage.ErrSlotNotFound {
+	if _, err := page.Remove([]byte("testkey10")); err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected remove result", res)
 		return
 	}
@@ -396,7 +396,7 @@ func TestHTreePageRemove(t *testing.T) {
 
 	sm.AccessMap[1] = storage.AccessUpdateError
 
-	if _, err := page.Remove([]byte("testkey9")); err != storage.ErrSlotNotFound {
+	if _, err := page.Remove([]byte("testkey9")); err.(*storage.StorageManagerError).Type != storage.ErrSlotNotFound {
 		t.Error("Unexpected remove result", res)
 		//return
 	}

+ 1 - 1
hash/iterator.go

@@ -105,7 +105,7 @@ func (it *HTreeIterator) nextItem() error {
 
 	if err != nil {
 
-		if err == storage.ErrSlotNotFound {
+		if smr, ok := err.(*storage.StorageManagerError); ok && smr.Type == storage.ErrSlotNotFound {
 
 			// Something is wrong - the tree must have changed since the last
 			// nextItem call. Remove the path element and try again.

+ 1 - 1
storage/cacheddiskstoragemanager.go

@@ -196,7 +196,7 @@ func (cdsm *CachedDiskStorageManager) FetchCached(loc uint64) (interface{}, erro
 		return entry.object, nil
 	}
 
-	return nil, ErrNotInCache
+	return nil, NewStorageManagerError(ErrNotInCache, "", cdsm.Name())
 }
 
 /*

+ 3 - 3
storage/cacheddiskstoragemanager_test.go

@@ -64,7 +64,7 @@ func TestCachedDiskStorageManager(t *testing.T) {
 
 	// Test getting non-existent entry from cache
 
-	if _, err := cdsm.FetchCached(loc + 1); err != ErrNotInCache {
+	if _, err := cdsm.FetchCached(loc + 1); err.(*StorageManagerError).Type != ErrNotInCache {
 		t.Error("Unexpected FetchCached result:", err)
 		return
 	}
@@ -239,7 +239,7 @@ func TestCachedDiskStorageManagerTransactions(t *testing.T) {
 	}
 
 	var ret string
-	if err := cdsm.Fetch(loc, &ret); err != ErrSlotNotFound ||
+	if err := cdsm.Fetch(loc, &ret); err.(*StorageManagerError).Type != ErrSlotNotFound ||
 		err.Error() != "Slot not found (ByteDiskStorageFile:storagemanagertest/ctest2 - Location:1 18)" {
 
 		t.Error("Unexpected fetch result:", err)
@@ -287,7 +287,7 @@ func TestCachedDiskStorageManagerTransactions(t *testing.T) {
 		return
 	}
 
-	if err := cdsm.Fetch(loc2, &ret); err != ErrSlotNotFound {
+	if err := cdsm.Fetch(loc2, &ret); err.(*StorageManagerError).Type != ErrSlotNotFound {
 		t.Error("Unexpected fetch result:", err)
 		return
 	}

+ 8 - 7
storage/diskstoragemanager.go

@@ -348,8 +348,8 @@ func (bdsm *ByteDiskStorageManager) Update(loc uint64, o interface{}) error {
 	}
 
 	if ploc == 0 {
-		return ErrSlotNotFound.fireError(bdsm, fmt.Sprint("Location:",
-			util.LocationRecord(loc), util.LocationOffset(loc)))
+		return NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:",
+			util.LocationRecord(loc), util.LocationOffset(loc)), bdsm.Name())
 	}
 
 	// Continue single threaded from here on
@@ -393,8 +393,8 @@ func (bdsm *ByteDiskStorageManager) Fetch(loc uint64, o interface{}) error {
 	}
 
 	if ploc == 0 {
-		return ErrSlotNotFound.fireError(bdsm, fmt.Sprint("Location:",
-			util.LocationRecord(loc), util.LocationOffset(loc)))
+		return NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:",
+			util.LocationRecord(loc), util.LocationOffset(loc)), bdsm.Name())
 	}
 
 	// Request the stored bytes
@@ -419,7 +419,8 @@ FetchCached is not implemented for a ByteDiskStorageManager.
 Only defined to satisfy the StorageManager interface.
 */
 func (bdsm *ByteDiskStorageManager) FetchCached(loc uint64) (interface{}, error) {
-	return nil, ErrNotInCache
+	return nil, NewStorageManagerError(ErrNotInCache, "", bdsm.Name())
+
 }
 
 /*
@@ -447,8 +448,8 @@ func (bdsm *ByteDiskStorageManager) Free(loc uint64) error {
 	}
 
 	if ploc == 0 {
-		return ErrSlotNotFound.fireError(bdsm, fmt.Sprint("Location:",
-			util.LocationRecord(loc), util.LocationOffset(loc)))
+		return NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:",
+			util.LocationRecord(loc), util.LocationOffset(loc)), bdsm.Name())
 	}
 
 	// First try to free the physical slot since here is the data

+ 5 - 5
storage/diskstoragemanager_test.go

@@ -205,7 +205,7 @@ func TestDiskStorageManager1(t *testing.T) {
 	flsp.StorageFile().ReleaseInUse(rflsp)
 
 	_, err = dsm.FetchCached(0)
-	if err != ErrNotInCache {
+	if err.(*StorageManagerError).Type != ErrNotInCache {
 		t.Error("Unexpected FetchCached result:", err)
 		return
 	}
@@ -270,7 +270,7 @@ func TestDiskStorageManager2(t *testing.T) {
 	}
 
 	err = dsm.Fetch(util.PackLocation(2, 18), &res)
-	if err != ErrSlotNotFound {
+	if err.(*StorageManagerError).Type != ErrSlotNotFound {
 		t.Error(err)
 		return
 	}
@@ -278,7 +278,7 @@ func TestDiskStorageManager2(t *testing.T) {
 	dsm.logicalSlotsSf.ReleaseInUse(record)
 
 	err = dsm.Fetch(util.PackLocation(3, 18), &res)
-	if err != ErrSlotNotFound {
+	if err.(*StorageManagerError).Type != ErrSlotNotFound {
 		t.Error(err)
 		return
 	}
@@ -300,7 +300,7 @@ func TestDiskStorageManager2(t *testing.T) {
 	dsm.logicalSlotsSf.ReleaseInUse(record)
 
 	err = dsm.Update(util.PackLocation(2, 18), "test")
-	if err != ErrSlotNotFound {
+	if err.(*StorageManagerError).Type != ErrSlotNotFound {
 		t.Error(err)
 		return
 	}
@@ -453,7 +453,7 @@ func TestDiskStorageManager3(t *testing.T) {
 
 	dsm := NewDiskStorageManager(DBDIR+"/test3", false, false, true, true)
 
-	if dsm.Free(util.PackLocation(2, 18)) != ErrSlotNotFound {
+	if dsm.Free(util.PackLocation(2, 18)).(*StorageManagerError).Type != ErrSlotNotFound {
 		t.Error("Unexpected free result")
 		return
 	}

+ 14 - 25
storage/globals.go

@@ -11,6 +11,7 @@
 package storage
 
 import (
+	"errors"
 	"fmt"
 
 	"devt.de/krotik/common/pools"
@@ -22,44 +23,32 @@ BufferPool is a pool of byte buffers.
 var BufferPool = pools.NewByteBufferPool()
 
 /*
-Common storage manager related errors. Having these global definitions
-makes the error comparison easier but has potential race-conditions.
-If two storage manager objects throw an error at the same time both errors
-will appear to come from the same instance.
+Common storage manager related errors.
 */
 var (
-	ErrSlotNotFound = newStorageManagerError("Slot not found")
-	ErrNotInCache   = newStorageManagerError("No entry in cache")
+	ErrSlotNotFound = errors.New("Slot not found")
+	ErrNotInCache   = errors.New("No entry in cache")
 )
 
 /*
-newStorageManagerError returns a new StorageManager specific error.
+StorageManagerError is a storage manager related error.
 */
-func newStorageManagerError(text string) *storagemanagerError {
-	return &storagemanagerError{text, "?", ""}
+type StorageManagerError struct {
+	Type        error
+	Detail      string
+	Managername string
 }
 
 /*
-StorageManager specific error datastructure
+NewStorageManagerError returns a new StorageManager specific error.
 */
-type storagemanagerError struct {
-	msg      string
-	filename string
-	info     string
-}
-
-/*
-fireError returns the error instance from a specific StorageManager instance.
-*/
-func (e *storagemanagerError) fireError(s Manager, info string) error {
-	e.filename = s.Name()
-	e.info = info
-	return e
+func NewStorageManagerError(smeType error, smeDetail string, smeManagername string) *StorageManagerError {
+	return &StorageManagerError{smeType, smeDetail, smeManagername}
 }
 
 /*
 Error returns a string representation of the error.
 */
-func (e *storagemanagerError) Error() string {
-	return fmt.Sprintf("%s (%s - %s)", e.msg, e.filename, e.info)
+func (e *StorageManagerError) Error() string {
+	return fmt.Sprintf("%s (%s - %s)", e.Type.Error(), e.Managername, e.Detail)
 }

+ 5 - 5
storage/memorystoragemanager.go

@@ -139,7 +139,7 @@ func (msm *MemoryStorageManager) Update(loc uint64, o interface{}) error {
 	defer msm.mutex.Unlock()
 
 	if msm.AccessMap[loc] == AccessUpdateError {
-		return ErrSlotNotFound.fireError(msm, fmt.Sprint("Location:", loc))
+		return NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:", loc), msm.Name())
 	}
 	msm.Data[loc] = o
 	return nil
@@ -153,7 +153,7 @@ func (msm *MemoryStorageManager) Free(loc uint64) error {
 	defer msm.mutex.Unlock()
 
 	if msm.AccessMap[loc] == AccessFreeError {
-		return ErrSlotNotFound.fireError(msm, fmt.Sprint("Location:", loc))
+		return NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:", loc), msm.Name())
 	}
 	delete(msm.Data, loc)
 	return nil
@@ -170,7 +170,7 @@ func (msm *MemoryStorageManager) Fetch(loc uint64, o interface{}) error {
 	defer msm.mutex.Unlock()
 
 	if msm.AccessMap[loc] == AccessFetchError || msm.AccessMap[loc] == AccessCacheAndFetchError {
-		return ErrSlotNotFound.fireError(msm, fmt.Sprint("Location:", loc))
+		return NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:", loc), msm.Name())
 	} else if msm.AccessMap[loc] == AccessCacheAndFetchSeriousError {
 		return file.NewStorageFileError(file.ErrAlreadyInUse, "", "<memory>")
 	}
@@ -178,7 +178,7 @@ func (msm *MemoryStorageManager) Fetch(loc uint64, o interface{}) error {
 	if obj, ok := msm.Data[loc]; ok {
 		err = datautil.CopyObject(obj, o)
 	} else {
-		err = ErrSlotNotFound.fireError(msm, fmt.Sprint("Location:", loc))
+		err = NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:", loc), msm.Name())
 	}
 	return err
 }
@@ -192,7 +192,7 @@ func (msm *MemoryStorageManager) FetchCached(loc uint64) (interface{}, error) {
 	defer msm.mutex.Unlock()
 
 	if msm.AccessMap[loc] == AccessNotInCache || msm.AccessMap[loc] == AccessCacheAndFetchError {
-		return nil, ErrNotInCache
+		return nil, NewStorageManagerError(ErrNotInCache, "", msm.Name())
 	} else if msm.AccessMap[loc] == AccessCacheAndFetchSeriousError {
 		return nil, file.NewStorageFileError(file.ErrAlreadyInUse, "", "<memory>")
 	}

+ 5 - 5
storage/memorystoragemanager_test.go

@@ -28,7 +28,7 @@ func TestMemoryStorageManager(t *testing.T) {
 		return
 	}
 
-	if err := msm.Fetch(5, &ret); err != ErrSlotNotFound {
+	if err := msm.Fetch(5, &ret); err.(*StorageManagerError).Type != ErrSlotNotFound {
 		t.Error("Unexpected fetch result:", err)
 		return
 	}
@@ -77,7 +77,7 @@ func TestMemoryStorageManager(t *testing.T) {
 
 	msm.AccessMap[loc] = AccessNotInCache
 
-	if _, err := msm.FetchCached(loc); err != ErrNotInCache {
+	if _, err := msm.FetchCached(loc); err.(*StorageManagerError).Type != ErrNotInCache {
 		t.Error("Unexpected fetchcached result:", err)
 		return
 	}
@@ -98,21 +98,21 @@ func TestMemoryStorageManager(t *testing.T) {
 
 	msm.AccessMap[loc] = AccessFetchError
 
-	if err := msm.Fetch(loc, &ret); err != ErrSlotNotFound {
+	if err := msm.Fetch(loc, &ret); err.(*StorageManagerError).Type != ErrSlotNotFound {
 		t.Error("Unexpected fetch result:", err)
 		return
 	}
 
 	msm.AccessMap[loc] = AccessUpdateError
 
-	if err := msm.Update(loc, ""); err != ErrSlotNotFound {
+	if err := msm.Update(loc, ""); err.(*StorageManagerError).Type != ErrSlotNotFound {
 		t.Error("Unexpected update result:", err)
 		return
 	}
 
 	msm.AccessMap[loc] = AccessFreeError
 
-	if err := msm.Free(loc); err != ErrSlotNotFound {
+	if err := msm.Free(loc); err.(*StorageManagerError).Type != ErrSlotNotFound {
 		t.Error("Unexpected free result:", err)
 		return
 	}