Skip to content

Commit

Permalink
reformat code
Browse files Browse the repository at this point in the history
  • Loading branch information
HDT3213 committed Apr 3, 2021
1 parent bf913a5 commit bcf0cd5
Show file tree
Hide file tree
Showing 54 changed files with 5,082 additions and 5,091 deletions.
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

[中文版](https://github.com/HDT3213/godis/blob/master/README_CN.md)

`Godis` is a simple implementation of Redis Server, which intents to provide an example of writing a high concurrent middleware using golang.
`Godis` is a simple implementation of Redis Server, which intents to provide an example of writing a high concurrent
middleware using golang.

Please be advised, NEVER think about using this in production environment.

This repository implemented most features of redis, including 5 data structures, ttl, publish/subscribe, AOF persistence and server side cluster mode.
This repository implemented most features of redis, including 5 data structures, ttl, publish/subscribe, AOF persistence
and server side cluster mode.

If you could read Chinese, you can find more details in [My Blog](https://www.cnblogs.com/Finley/category/1598973.html).

Expand All @@ -22,7 +24,7 @@ You could use redis-cli or other redis client to connect godis server, which lis

The program will try to read config file path from environment variable `CONFIG`.

If environment variable is not set, then the program try to read `redis.conf` in the working directory.
If environment variable is not set, then the program try to read `redis.conf` in the working directory.

If there is no such file, then the program will run with default config.

Expand All @@ -35,8 +37,7 @@ peers localhost:7379,localhost:7389 // other node in cluster
self localhost:6399 // self address
```

We provide node1.conf and node2.conf for demonstration.
use following command line to start a two-node-cluster:
We provide node1.conf and node2.conf for demonstration. use following command line to start a two-node-cluster:

```bash
CONFIG=node1.conf ./godis-darwin &
Expand Down Expand Up @@ -151,7 +152,7 @@ Supported Commands:
If you want to read my code in this repository, here is a simple guidance.

- cmd: only the entry point
- config: config parser
- config: config parser
- interface: some interface definitions
- lib: some utils, such as logger, sync utils and wildcard

Expand All @@ -167,7 +168,7 @@ I suggest focusing on the following directories:
- sortedset: a sorted set implements based on skiplist
- db: the implements of the redis db
- db.go: the basement of database
- router.go: it find handler for commands
- router.go: it find handler for commands
- keys.go: handlers for keys commands
- string.go: handlers for string commands
- list.go: handlers for list commands
Expand All @@ -176,7 +177,7 @@ I suggest focusing on the following directories:
- sortedset.go: handlers for sorted set commands
- pubsub.go: implements of publish / subscribe
- aof.go: implements of AOF persistence and rewrite

# License

This project is licensed under the [GPL license](https://github.com/HDT3213/godis/blob/master/LICENSE).
34 changes: 17 additions & 17 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ Godis 是一个用 Go 语言实现的 Redis 服务器。本项目旨在为尝试

**请注意:不要在生产环境使用使用此项目**

Godis 实现了 Redis 的大多数功能,包括5种数据结构、TTL、发布订阅以及 AOF 持久化。可以在[我的博客](https://www.cnblogs.com/Finley/category/1598973.html)了解更多关于 Godis 的信息。

Godis 实现了 Redis 的大多数功能,包括5种数据结构、TTL、发布订阅以及 AOF 持久化。可以在[我的博客](https://www.cnblogs.com/Finley/category/1598973.html)了解更多关于
Godis 的信息。

# 运行 Godis

Expand Down Expand Up @@ -149,19 +149,19 @@ redis-cli -p 6399
- tcp: tcp 服务器实现
- redis: redis 协议解析器
- datastruct: redis 的各类数据结构实现
- dict: hash 表
- list: 链表
- lock: 用于锁定 key 的锁组件
- set: 基于hash表的集合
- sortedset: 基于跳表实现的有序集合
- dict: hash 表
- list: 链表
- lock: 用于锁定 key 的锁组件
- set: 基于hash表的集合
- sortedset: 基于跳表实现的有序集合
- db: redis 存储引擎实现
- db.go: 引擎的基础功能
- router.go: 将命令路由给响应的处理函数
- keys.go: del、ttl、expire 等通用命令实现
- string.go: get、set 等字符串命令实现
- list.go: lpush、lindex 等列表命令实现
- hash.go: hget、hset 等哈希表命令实现
- set.go: sadd 等集合命令实现
- sortedset.go: zadd 等有序集合命令实现
- pubsub.go: 发布订阅命令实现
- aof.go: aof持久化实现
- db.go: 引擎的基础功能
- router.go: 将命令路由给响应的处理函数
- keys.go: del、ttl、expire 等通用命令实现
- string.go: get、set 等字符串命令实现
- list.go: lpush、lindex 等列表命令实现
- hash.go: hget、hset 等哈希表命令实现
- set.go: sadd 等集合命令实现
- sortedset.go: zadd 等有序集合命令实现
- pubsub.go: 发布订阅命令实现
- aof.go: aof持久化实现
46 changes: 23 additions & 23 deletions src/cluster/client.go
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
package cluster

import (
"context"
"errors"
"github.com/HDT3213/godis/src/redis/client"
"github.com/jolestar/go-commons-pool/v2"
"context"
"errors"
"github.com/HDT3213/godis/src/redis/client"
"github.com/jolestar/go-commons-pool/v2"
)

type ConnectionFactory struct {
Peer string
Peer string
}

func (f *ConnectionFactory) MakeObject(ctx context.Context) (*pool.PooledObject, error) {
c, err := client.MakeClient(f.Peer)
if err != nil {
return nil, err
}
c.Start()
return pool.NewPooledObject(c), nil
c, err := client.MakeClient(f.Peer)
if err != nil {
return nil, err
}
c.Start()
return pool.NewPooledObject(c), nil
}

func (f *ConnectionFactory) DestroyObject(ctx context.Context, object *pool.PooledObject) error {
c, ok := object.Object.(*client.Client)
if !ok {
return errors.New("type mismatch")
}
c.Close()
return nil
c, ok := object.Object.(*client.Client)
if !ok {
return errors.New("type mismatch")
}
c.Close()
return nil
}

func (f *ConnectionFactory) ValidateObject(ctx context.Context, object *pool.PooledObject) bool {
// do validate
return true
// do validate
return true
}

func (f *ConnectionFactory) ActivateObject(ctx context.Context, object *pool.PooledObject) error {
// do activate
return nil
// do activate
return nil
}

func (f *ConnectionFactory) PassivateObject(ctx context.Context, object *pool.PooledObject) error {
// do passivate
return nil
// do passivate
return nil
}
166 changes: 83 additions & 83 deletions src/cluster/del.go
Original file line number Diff line number Diff line change
@@ -1,99 +1,99 @@
package cluster

import (
"github.com/HDT3213/godis/src/interface/redis"
"github.com/HDT3213/godis/src/redis/reply"
"strconv"
"github.com/HDT3213/godis/src/interface/redis"
"github.com/HDT3213/godis/src/redis/reply"
"strconv"
)

func Del(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
if len(args) < 2 {
return reply.MakeErrReply("ERR wrong number of arguments for 'del' command")
}
keys := make([]string, len(args)-1)
for i := 1; i < len(args); i++ {
keys[i-1] = string(args[i])
}
groupMap := cluster.groupBy(keys)
if len(groupMap) == 1 { // do fast
for peer, group := range groupMap { // only one group
return cluster.Relay(peer, c, makeArgs("DEL", group...))
}
}
// prepare
var errReply redis.Reply
txId := cluster.idGenerator.NextId()
txIdStr := strconv.FormatInt(txId, 10)
rollback := false
for peer, group := range groupMap {
args := []string{txIdStr}
args = append(args, group...)
var resp redis.Reply
if peer == cluster.self {
resp = PrepareDel(cluster, c, makeArgs("PrepareDel", args...))
} else {
resp = cluster.Relay(peer, c, makeArgs("PrepareDel", args...))
}
if reply.IsErrorReply(resp) {
errReply = resp
rollback = true
break
}
}
var respList []redis.Reply
if rollback {
// rollback
RequestRollback(cluster, c, txId, groupMap)
} else {
// commit
respList, errReply = RequestCommit(cluster, c, txId, groupMap)
if errReply != nil {
rollback = true
}
}
if !rollback {
var deleted int64 = 0
for _, resp := range respList {
intResp := resp.(*reply.IntReply)
deleted += intResp.Code
}
return reply.MakeIntReply(int64(deleted))
}
return errReply
if len(args) < 2 {
return reply.MakeErrReply("ERR wrong number of arguments for 'del' command")
}
keys := make([]string, len(args)-1)
for i := 1; i < len(args); i++ {
keys[i-1] = string(args[i])
}
groupMap := cluster.groupBy(keys)
if len(groupMap) == 1 { // do fast
for peer, group := range groupMap { // only one group
return cluster.Relay(peer, c, makeArgs("DEL", group...))
}
}
// prepare
var errReply redis.Reply
txId := cluster.idGenerator.NextId()
txIdStr := strconv.FormatInt(txId, 10)
rollback := false
for peer, group := range groupMap {
args := []string{txIdStr}
args = append(args, group...)
var resp redis.Reply
if peer == cluster.self {
resp = PrepareDel(cluster, c, makeArgs("PrepareDel", args...))
} else {
resp = cluster.Relay(peer, c, makeArgs("PrepareDel", args...))
}
if reply.IsErrorReply(resp) {
errReply = resp
rollback = true
break
}
}
var respList []redis.Reply
if rollback {
// rollback
RequestRollback(cluster, c, txId, groupMap)
} else {
// commit
respList, errReply = RequestCommit(cluster, c, txId, groupMap)
if errReply != nil {
rollback = true
}
}
if !rollback {
var deleted int64 = 0
for _, resp := range respList {
intResp := resp.(*reply.IntReply)
deleted += intResp.Code
}
return reply.MakeIntReply(int64(deleted))
}
return errReply
}

// args: PrepareDel id keys...
func PrepareDel(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
if len(args) < 3 {
return reply.MakeErrReply("ERR wrong number of arguments for 'preparedel' command")
}
txId := string(args[1])
keys := make([]string, 0, len(args)-2)
for i := 2; i < len(args); i++ {
arg := args[i]
keys = append(keys, string(arg))
}
txArgs := makeArgs("DEL", keys...) // actual args for cluster.db
tx := NewTransaction(cluster, c, txId, txArgs, keys)
cluster.transactions.Put(txId, tx)
err := tx.prepare()
if err != nil {
return reply.MakeErrReply(err.Error())
}
return &reply.OkReply{}
if len(args) < 3 {
return reply.MakeErrReply("ERR wrong number of arguments for 'preparedel' command")
}
txId := string(args[1])
keys := make([]string, 0, len(args)-2)
for i := 2; i < len(args); i++ {
arg := args[i]
keys = append(keys, string(arg))
}
txArgs := makeArgs("DEL", keys...) // actual args for cluster.db
tx := NewTransaction(cluster, c, txId, txArgs, keys)
cluster.transactions.Put(txId, tx)
err := tx.prepare()
if err != nil {
return reply.MakeErrReply(err.Error())
}
return &reply.OkReply{}
}

// invoker should provide lock
func CommitDel(cluster *Cluster, c redis.Connection, tx *Transaction) redis.Reply {
keys := make([]string, len(tx.args))
for i, v := range tx.args {
keys[i] = string(v)
}
keys = keys[1:]
keys := make([]string, len(tx.args))
for i, v := range tx.args {
keys[i] = string(v)
}
keys = keys[1:]

deleted := cluster.db.Removes(keys...)
if deleted > 0 {
cluster.db.AddAof(reply.MakeMultiBulkReply(tx.args))
}
return reply.MakeIntReply(int64(deleted))
deleted := cluster.db.Removes(keys...)
if deleted > 0 {
cluster.db.AddAof(reply.MakeMultiBulkReply(tx.args))
}
return reply.MakeIntReply(int64(deleted))
}
Loading

0 comments on commit bcf0cd5

Please sign in to comment.