diff options
| author | alex <[email protected]> | 2026-07-10 20:28:47 +0200 |
|---|---|---|
| committer | alex <[email protected]> | 2026-07-10 20:28:47 +0200 |
| commit | f18210c30e67de4bede7c6080d85629f7086676c (patch) | |
| tree | c9aedf21ed9f905424f8ab6fdb633254e127fbc6 /pkg/core/shards.go | |
| parent | 36d70e64340033f1e5b928524436c0b2f44c831e (diff) | |
| download | redis-clone-f18210c30e67de4bede7c6080d85629f7086676c.tar.xz redis-clone-f18210c30e67de4bede7c6080d85629f7086676c.zip | |
separated commands into their own files TODO: refactor all commands to work like this
Diffstat (limited to 'pkg/core/shards.go')
| -rw-r--r-- | pkg/core/shards.go | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/pkg/core/shards.go b/pkg/core/shards.go new file mode 100644 index 0000000..5ede61c --- /dev/null +++ b/pkg/core/shards.go @@ -0,0 +1,134 @@ +package core + +import ( + "hash/fnv" + "sort" + "sync" +) +const NumShards = 16 + +type Shard struct{ + Mu sync.RWMutex + Id int + Data map[string]Item +} + +func (db *RedisDB) GetShard(key string)*Shard{ + hash := fnv.New64a() + hash.Write([]byte(key)) + val := hash.Sum64() + + return db.Shards[val%NumShards] +} + +func (db *RedisDB) Execute(key string, fn func(*Shard) interface{}) interface{} { + shard := db.GetShard(key) + shard.Mu.Lock() + defer shard.Mu.Unlock() + return fn(shard) +} +func (db *RedisDB) ExecuteRead(key string, fn func(*Shard) interface{}) interface{} { + shard := db.GetShard(key) + shard.Mu.RLock() + defer shard.Mu.RUnlock() + return fn(shard) +} +func ( db *RedisDB) ExecuteMulti(keys []string, fn func([]*Shard) interface{})interface{}{ + if len(keys) == 1{ + shard := db.GetShard(keys[0]) + shard.Mu.Lock() + defer shard.Mu.Unlock() + Shards := []*Shard{shard} + return fn(Shards) + }else{ + shardMap := make(map[int]*Shard) + for _, k := range keys { + shard := db.GetShard(k) + shardMap[shard.Id] = shard + } + var sortedIDs []int + for Id := range shardMap { + sortedIDs = append(sortedIDs, Id) + } + sort.Ints(sortedIDs) + for _, Id := range sortedIDs{ + shardMap[Id].Mu.Lock() + } + defer func(){ + for i := len(sortedIDs)-1; i >= 0; i --{ + shardMap[sortedIDs[i]].Mu.Unlock() + } + }() + + Shards := make([]*Shard, 0, len(shardMap)) + for _, Id := range sortedIDs { + Shards = append(Shards, shardMap[Id]) + } + return fn(Shards) + } +} + +func ( db *RedisDB) ExecuteAll(fn func([]*Shard) interface{})interface{}{ + for _, shard := range db.Shards { + shard.Mu.Lock() + } + + defer func(){ + for i := len(db.Shards)-1;i >= 0; i --{ + db.Shards[i].Mu.Unlock() + } + }() + + return fn(db.Shards) +} + +func ( db *RedisDB) ExecuteReadAll(fn func([]*Shard) interface{})interface{}{ + for _, shard := range db.Shards { + shard.Mu.RLock() + } + + defer func(){ + for i := len(db.Shards)-1;i >= 0; i --{ + db.Shards[i].Mu.RUnlock() + } + }() + + return fn(db.Shards) +} + +func ( db *RedisDB) Lock(keys []string){ + if len(keys) == 1{ + shard := db.GetShard(keys[0]) + shard.Mu.Lock() + }else{ + shardMap := make(map[int]*Shard) + for _, k := range keys { + shard := db.GetShard(k) + shardMap[shard.Id] = shard + } + var sortedIDs []int + for Id := range shardMap { + sortedIDs = append(sortedIDs, Id) + } + sort.Ints(sortedIDs) + for _, Id := range sortedIDs{ + shardMap[Id].Mu.Lock() + } + } +} +func ( db *RedisDB) Unlock(keys []string){ + shardMap := make(map[int]*Shard) + for _, k := range keys { + shard := db.GetShard(k) + shardMap[shard.Id] = shard + } + var sortedIDs []int + for Id := range shardMap { + sortedIDs = append(sortedIDs, Id) + } + sort.Ints(sortedIDs) + + for i := len(sortedIDs)-1; i >= 0; i --{ + shardMap[sortedIDs[i]].Mu.Unlock() + } +}
\ No newline at end of file |
