From 754ace9023f852910fd8e07bddea8500d7b4b76b Mon Sep 17 00:00:00 2001
From: Hans Moog <hm@mkjc.net>
Date: Fri, 5 Jul 2019 17:13:51 +0200
Subject: [PATCH] Feat: added a KRWMutex which allows locking per unique id

---
 packages/datastructure/krw_mutex.go      | 53 ++++++++++++++++++++++++
 packages/datastructure/krw_mutex_test.go | 23 ++++++++++
 plugins/tangle/transaction_metadata.go   |  3 --
 3 files changed, 76 insertions(+), 3 deletions(-)
 create mode 100644 packages/datastructure/krw_mutex.go
 create mode 100644 packages/datastructure/krw_mutex_test.go

diff --git a/packages/datastructure/krw_mutex.go b/packages/datastructure/krw_mutex.go
new file mode 100644
index 00000000..2b05ce37
--- /dev/null
+++ b/packages/datastructure/krw_mutex.go
@@ -0,0 +1,53 @@
+package datastructure
+
+import (
+	"sync"
+)
+
+type KRWMutex struct {
+	keyMutexConsumers map[interface{}]int
+	keyMutexes        map[interface{}]*sync.RWMutex
+	mutex             sync.RWMutex
+}
+
+func NewKRWMutex() *KRWMutex {
+	return &KRWMutex{
+		keyMutexConsumers: make(map[interface{}]int),
+		keyMutexes:        make(map[interface{}]*sync.RWMutex),
+	}
+}
+
+func (krwMutex *KRWMutex) Register(key interface{}) (result *sync.RWMutex) {
+	krwMutex.mutex.Lock()
+
+	if val, exists := krwMutex.keyMutexConsumers[key]; exists {
+		krwMutex.keyMutexConsumers[key] = val + 1
+		result = krwMutex.keyMutexes[key]
+	} else {
+		result = &sync.RWMutex{}
+
+		krwMutex.keyMutexConsumers[key] = 1
+		krwMutex.keyMutexes[key] = result
+	}
+
+	krwMutex.mutex.Unlock()
+
+	return
+}
+
+func (kwrMutex *KRWMutex) Free(key interface{}) {
+	kwrMutex.mutex.Lock()
+
+	if val, exists := kwrMutex.keyMutexConsumers[key]; exists {
+		if val == 1 {
+			delete(kwrMutex.keyMutexConsumers, key)
+			delete(kwrMutex.keyMutexes, key)
+		} else {
+			kwrMutex.keyMutexConsumers[key] = val - 1
+		}
+	} else {
+		panic("trying to free non-existent key")
+	}
+
+	kwrMutex.mutex.Unlock()
+}
diff --git a/packages/datastructure/krw_mutex_test.go b/packages/datastructure/krw_mutex_test.go
new file mode 100644
index 00000000..bb5290ab
--- /dev/null
+++ b/packages/datastructure/krw_mutex_test.go
@@ -0,0 +1,23 @@
+package datastructure
+
+import (
+	"testing"
+)
+
+func TestKRWMutex_Free(t *testing.T) {
+	krwMutex := NewKRWMutex()
+
+	krwMutex.Register("test")
+	krwMutex.Register("test")
+	krwMutex.Free("test")
+	krwMutex.Free("test")
+}
+
+func BenchmarkKRWMutex(b *testing.B) {
+	krwMutex := NewKRWMutex()
+
+	for i := 0; i < b.N; i++ {
+		krwMutex.Register(i)
+		krwMutex.Free(i)
+	}
+}
diff --git a/plugins/tangle/transaction_metadata.go b/plugins/tangle/transaction_metadata.go
index 6548346b..82a3b8fd 100644
--- a/plugins/tangle/transaction_metadata.go
+++ b/plugins/tangle/transaction_metadata.go
@@ -90,9 +90,6 @@ func storeTransactionMetadataInDatabase(metadata *transactionmetadata.Transactio
 		if marshaledMetadata, err := metadata.Marshal(); err != nil {
 			return err
 		} else {
-			if len(marshaledMetadata) != 97 {
-				panic("WATT")
-			}
 			if err := transactionMetadataDatabase.Set(metadata.GetHash().CastToBytes(), marshaledMetadata); err != nil {
 				return ErrDatabaseError.Derive(err, "failed to store transaction metadata")
 			}
-- 
GitLab