Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

支持对 Tair Stack 中TairString、TairHash、TairZset三种数据结构编码的解析 #657

Merged
merged 4 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ jobs:
strategy:
matrix:
redis-version: [ "2.8", "3.0", "4.0", "5.0", "6.0", "7.0" ]
fail-fast: false
container: ubuntu:latest
steps:
- name: Git checkout
Expand All @@ -30,6 +31,45 @@ jobs:
cp src/redis-server bin/redis-server
echo "$GITHUB_WORKSPACE/redis/bin" >> $GITHUB_PATH

- name: clone and make TairString Module
if: contains( '5.0, 6.0, 7.0', matrix.redis-version)
run: |
cd $GITHUB_WORKSPACE
apt-get install -y cmake
git clone https://github.com/tair-opensource/TairString.git
cd TairString
mkdir build
cd build
cmake ../ && make -j
cp $GITHUB_WORKSPACE/TairString/lib/tairstring_module.so /lib



- name: clone and make TairHash Module
if: contains( '5.0, 6.0, 7.0', matrix.redis-version)
run: |
cd $GITHUB_WORKSPACE
git clone https://github.com/tair-opensource/TairHash.git
cd TairHash
mkdir build
cd build
cmake ../ && make -j
cp $GITHUB_WORKSPACE/TairHash/lib/tairhash_module.so /lib



- name: clone and make TairZset Module
if: contains( '5.0, 6.0, 7.0', matrix.redis-version)
run: |
cd $GITHUB_WORKSPACE
git clone https://github.com/tair-opensource/TairZset.git
cd TairZset
mkdir build
cd build
cmake ../ && make -j
cp $GITHUB_WORKSPACE/TairZset/lib/tairzset_module.so /lib


- name: Setup Python
uses: actions/setup-python@v4
with:
Expand Down
54 changes: 54 additions & 0 deletions internal/commands/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -4505,4 +4505,58 @@ var redisCommands = map[string]redisCommand{
},
},
},
"EXHSET": {
"TAIRHASH",
[]keySpec{
{
"index",
1,
"",
0,
"range",
0,
1,
0,
0,
0,
0,
},
},
},
"EXSET": {
"TAIRSTRING",
[]keySpec{
{
"index",
1,
"",
0,
"range",
0,
1,
0,
0,
0,
0,
},
},
},
"EXZADD": {
"TAIRZSET",
[]keySpec{
{
"index",
1,
"",
0,
"range",
0,
1,
0,
0,
0,
0,
},
},
},
}
71 changes: 71 additions & 0 deletions internal/rdb/structure/module2_struct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package structure

import (
"fmt"
"io"
"log"
"strconv"
)

const (
rdbModuleOpcodeEOF = 0 // End of module value.
rdbModuleOpcodeSINT = 1 // Signed integer.
rdbModuleOpcodeUINT = 2 // Unsigned integer.
rdbModuleOpcodeFLOAT = 3 // Float.
rdbModuleOpcodeDOUBLE = 4 // Double.
rdbModuleOpcodeSTRING = 5 // String.
)

func ReadModuleUnsigned(rd io.Reader) string {
opcode := ReadByte(rd)
if opcode != rdbModuleOpcodeUINT {
log.Panicf("Unknown module unsigned encode type")
}
value := ReadLength(rd)
return strconv.FormatUint(value, 10)
}

func ReadModuleSigned(rd io.Reader) string {
opcode := ReadByte(rd)
if opcode != rdbModuleOpcodeSINT {
log.Panicf("Unknown module signed encode type")
}
value := ReadLength(rd)
return strconv.FormatUint(value, 10)
}

func ReadModuleFloat(rd io.Reader) string {
opcode := ReadByte(rd)
if opcode != rdbModuleOpcodeDOUBLE {

log.Panicf("Unknown module double encode type")
}
value := ReadDouble(rd)
return fmt.Sprintf("%f", value)
}

func ReadModuleDouble(rd io.Reader) string {
opcode := ReadByte(rd)
if opcode != rdbModuleOpcodeDOUBLE {
log.Panicf("Unknown module double encode type")
}
value := ReadDouble(rd)
return fmt.Sprintf("%f", value)
}

func ReadModuleString(rd io.Reader) string {
opcode := ReadByte(rd)
if opcode != rdbModuleOpcodeSTRING {
log.Panicf("Unknown module string encode type")
}
return ReadString(rd)
}

func ReadModuleEof(rd io.Reader) error {
eof := ReadLength(rd)
if eof != rdbModuleOpcodeEOF {
log.Panicf("The RDB file is not teminated by the proper module value EOF marker")
}
return nil

}
3 changes: 1 addition & 2 deletions internal/rdb/types/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ func ParseObject(rd io.Reader, typeByte byte, key string) RedisObject {
o.LoadFromBuffer(rd, key, typeByte)
return o
case rdbTypeModule, rdbTypeModule2: // module
o := new(ModuleObject)
o.LoadFromBuffer(rd, key, typeByte)
o := PareseModuleType(rd, key, typeByte)
return o
}
log.Panicf("unknown type byte: %d", typeByte)
Expand Down
45 changes: 22 additions & 23 deletions internal/rdb/types/module2.go
Original file line number Diff line number Diff line change
@@ -1,40 +1,39 @@
package types

import (
"io"

"RedisShake/internal/log"
"RedisShake/internal/rdb/structure"
"io"
)

type ModuleObject struct {
type ModuleObject interface {
RedisObject
}

func (o *ModuleObject) LoadFromBuffer(rd io.Reader, key string, typeByte byte) {
func PareseModuleType(rd io.Reader, key string, typeByte byte) ModuleObject {
if typeByte == rdbTypeModule {
log.Panicf("module type with version 1 is not supported, key=[%s]", key)
}
moduleId := structure.ReadLength(rd)
moduleName := moduleTypeNameByID(moduleId)
opcode := structure.ReadByte(rd)
for opcode != rdbModuleOpcodeEOF {
switch opcode {
case rdbModuleOpcodeSINT:
case rdbModuleOpcodeUINT:
structure.ReadLength(rd)
case rdbModuleOpcodeFLOAT:
structure.ReadFloat(rd)
case rdbModuleOpcodeDOUBLE:
structure.ReadDouble(rd)
case rdbModuleOpcodeSTRING:
structure.ReadString(rd)
default:
log.Panicf("unknown module opcode=[%d], module name=[%s]", opcode, moduleName)
}
opcode = structure.ReadByte(rd)
switch moduleName {
case "exstrtype":
o := new(TairStringObject)
o.LoadFromBuffer(rd, key, typeByte)
return o
case "tairhash-":
o := new(TairHashObject)
o.LoadFromBuffer(rd, key, typeByte)
return o
case "tairzset_":
o := new(TairZsetObject)
o.LoadFromBuffer(rd, key, typeByte)
return o
default:
log.Panicf("unsupported module type: %s", moduleName)
return nil

}
}

func (o *ModuleObject) Rewrite() []RedisCmd {
log.Panicf("module Rewrite not implemented")
return nil
}
57 changes: 57 additions & 0 deletions internal/rdb/types/tairhash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package types

import (
"io"
"strconv"

"RedisShake/internal/rdb/structure"
)

type TairHashValue struct {
skey string
version string
expire string
fieldValue string
}

type TairHashObject struct {
dictSize string
key string
value []TairHashValue
}

func (o *TairHashObject) LoadFromBuffer(rd io.Reader, key string, typeByte byte) {
o.dictSize = structure.ReadModuleUnsigned(rd)
o.key = structure.ReadModuleString(rd)

size, _ := strconv.Atoi(o.dictSize)
for i := 0; i < size; i++ {
hashValue := TairHashValue{
structure.ReadModuleString(rd),
structure.ReadModuleUnsigned(rd),
structure.ReadModuleUnsigned(rd),
structure.ReadModuleString(rd),
}
o.value = append(o.value, hashValue)
}
structure.ReadModuleEof(rd)
}

func (o *TairHashObject) Rewrite() []RedisCmd {
var cmds []RedisCmd
size, _ := strconv.Atoi(o.dictSize)
for i := 0; i < size; i++ {
cmd := []string{}
expire, _ := strconv.Atoi(o.value[i].expire)
if expire == 0 {
cmd = append(cmd, "EXHSET", o.key, o.value[i].skey, o.value[i].fieldValue)
} else {
cmd = append(cmd, "EXHSET", o.key, o.value[i].skey, o.value[i].fieldValue,
"ABS", o.value[i].version,
"PXAT", o.value[i].expire)
}

cmds = append(cmds, cmd)
}
return cmds
}
32 changes: 32 additions & 0 deletions internal/rdb/types/tairstring.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package types

import (
"io"

"RedisShake/internal/rdb/structure"
)

type TairStringValue struct {
version string
flags string
tairValue string
}

type TairStringObject struct {
value TairStringValue
key string
}

func (o *TairStringObject) LoadFromBuffer(rd io.Reader, key string, typeByte byte) {
o.key = key
o.value.version = structure.ReadModuleUnsigned(rd)
o.value.flags = structure.ReadModuleUnsigned(rd)
o.value.tairValue = structure.ReadModuleString(rd)
structure.ReadModuleEof(rd)
}

func (o *TairStringObject) Rewrite() []RedisCmd {
cmd := RedisCmd{}
cmd = append(cmd, "EXSET", o.key, o.value.tairValue, "ABS", o.value.version, "FLAGS", o.value.flags)
return []RedisCmd{cmd}
}
46 changes: 46 additions & 0 deletions internal/rdb/types/tairzset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package types

import (
"io"
"strconv"
"strings"

"RedisShake/internal/rdb/structure"
)

type TairZsetObject struct {
key string
length string
scoreNum string
value map[string][]string
}

func (o *TairZsetObject) LoadFromBuffer(rd io.Reader, key string, typeByte byte) {
o.key = key
o.length = structure.ReadModuleUnsigned(rd)
o.scoreNum = structure.ReadModuleUnsigned(rd)

len, _ := strconv.Atoi(o.length)
scoreNum, _ := strconv.Atoi(o.scoreNum)
valueMap := make(map[string][]string)
for i := 0; i < len; i++ {
key := structure.ReadModuleString(rd)
values := []string{}
for j := 0; j < scoreNum; j++ {
values = append(values, structure.ReadModuleDouble(rd))
}
valueMap[key] = values
}
o.value = valueMap
structure.ReadModuleEof(rd)
}

func (o *TairZsetObject) Rewrite() []RedisCmd {
var cmds []RedisCmd
for k, v := range o.value {
score := strings.Join(v, "#")
cmd := RedisCmd{"EXZADD", o.key, score, k}
cmds = append(cmds, cmd)
}
return cmds
}
Loading
Loading