diff --git a/internal/rdb/types/interface.go b/internal/rdb/types/interface.go index 1e237d75..03ba67e3 100644 --- a/internal/rdb/types/interface.go +++ b/internal/rdb/types/interface.go @@ -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) diff --git a/internal/rdb/types/module2.go b/internal/rdb/types/module2.go index 73e01b06..3646f781 100644 --- a/internal/rdb/types/module2.go +++ b/internal/rdb/types/module2.go @@ -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 } diff --git a/internal/rdb/types/tairhash.go b/internal/rdb/types/tairhash.go new file mode 100644 index 00000000..7476bd82 --- /dev/null +++ b/internal/rdb/types/tairhash.go @@ -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 +} diff --git a/internal/rdb/types/tairstring.go b/internal/rdb/types/tairstring.go new file mode 100644 index 00000000..e5db7dbd --- /dev/null +++ b/internal/rdb/types/tairstring.go @@ -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} +} diff --git a/internal/rdb/types/tairzset.go b/internal/rdb/types/tairzset.go new file mode 100644 index 00000000..52f75b54 --- /dev/null +++ b/internal/rdb/types/tairzset.go @@ -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 +}