implemented interface gob encode and decode for redit cacher

This commit is contained in:
Nash Tsai 2014-08-08 04:10:35 +08:00
parent 40f3ddd819
commit 4c93eaf1f4
1 changed files with 65 additions and 10 deletions

View File

@ -6,6 +6,7 @@ import (
"fmt"
"github.com/garyburd/redigo/redis"
//"github.com/go-xorm/core"
"log"
"reflect"
"strconv"
"time"
@ -86,11 +87,15 @@ func (c *RedisCacher) getObject(key string) interface{} {
if raw == nil {
return nil
}
_, err = redis.Bytes(raw, err) // TODO: item, err := redis.Bytes(raw, err)
item, err := redis.Bytes(raw, err)
if err != nil {
return err
log.Fatalf("xorm/cache: redis.Bytes failed: %s", err)
return nil
}
return nil //Deserialize(item, ptrValue) // TODO
value, err := Deserialize(item)
return value
}
func (c *RedisCacher) GetIds(tableName, sql string) interface{} {
@ -197,10 +202,12 @@ func Serialize(value interface{}) ([]byte, error) {
return []byte(strconv.FormatUint(v.Uint(), 10)), nil
}
RegisterGobConcreteType(value)
var b bytes.Buffer
encoder := gob.NewEncoder(&b)
if err := encoder.Encode(value); err != nil {
// revel.ERROR.Printf("revel/cache: gob encoding '%s' failed: %s", value, err)
if err := interfaceEncode(encoder, value); err != nil {
log.Fatalf("xorm/cache: gob encoding '%s' failed: %s", value, err)
return nil, err
}
return b.Bytes(), nil
@ -208,7 +215,7 @@ func Serialize(value interface{}) ([]byte, error) {
// Deserialize transforms bytes produced by Serialize back into a Go object,
// storing it into "ptr", which must be a pointer to the value type.
func Deserialize(byt []byte, ptr interface{}) (err error) {
func Deserialize(byt []byte) (ptr interface{}, err error) {
if bytes, ok := ptr.(*[]byte); ok {
*bytes = byt
return
@ -220,7 +227,7 @@ func Deserialize(byt []byte, ptr interface{}) (err error) {
var i int64
i, err = strconv.ParseInt(string(byt), 10, 64)
if err != nil {
// revel.ERROR.Printf("revel/cache: failed to parse int '%s': %s", string(byt), err)
log.Fatalf("xorm/cache: failed to parse int '%s': %s", string(byt), err)
} else {
p.SetInt(i)
}
@ -230,7 +237,7 @@ func Deserialize(byt []byte, ptr interface{}) (err error) {
var i uint64
i, err = strconv.ParseUint(string(byt), 10, 64)
if err != nil {
// revel.ERROR.Printf("revel/cache: failed to parse uint '%s': %s", string(byt), err)
log.Fatalf("xorm/cache: failed to parse uint '%s': %s", string(byt), err)
} else {
p.SetUint(i)
}
@ -240,9 +247,57 @@ func Deserialize(byt []byte, ptr interface{}) (err error) {
b := bytes.NewBuffer(byt)
decoder := gob.NewDecoder(b)
if err = decoder.Decode(ptr); err != nil {
// revel.ERROR.Printf("revel/cache: gob decoding failed: %s", err)
if ptr, err = interfaceDecode(decoder); err != nil {
log.Fatalf("xorm/cache: gob decoding failed: %s", err)
return
}
return
}
func RegisterGobConcreteType(value interface{}) {
t := reflect.TypeOf(value)
switch t.Kind() {
case reflect.Ptr:
v := reflect.ValueOf(value)
i := v.Elem().Interface()
gob.Register(i)
case reflect.Struct:
gob.Register(value)
case reflect.Slice:
fallthrough
case reflect.Map:
fallthrough
default:
panic(fmt.Errorf("unhandled type: %v", t))
}
}
// interfaceEncode encodes the interface value into the encoder.
func interfaceEncode(enc *gob.Encoder, p interface{}) error {
// The encode will fail unless the concrete type has been
// registered. We registered it in the calling function.
// Pass pointer to interface so Encode sees (and hence sends) a value of
// interface type. If we passed p directly it would see the concrete type instead.
// See the blog post, "The Laws of Reflection" for background.
err := enc.Encode(&p)
if err != nil {
log.Fatal("encode:", err)
}
return err
}
// interfaceDecode decodes the next interface value from the stream and returns it.
func interfaceDecode(dec *gob.Decoder) (interface{}, error) {
// The decode will fail unless the concrete type on the wire has been
// registered. We registered it in the calling function.
var p interface{}
err := dec.Decode(&p)
if err != nil {
log.Fatal("decode:", err)
}
return p, err
}