ybc icon indicating copy to clipboard operation
ybc copied to clipboard

Cant store json in ybc using golang

Open vektah opened this issue 8 years ago • 4 comments

Not sure what is going on here...

package main

import (
    "encoding/json"
    "github.com/valyala/ybc/bindings/go/ybc"
    "time"
)

func main() {
    cfg := &ybc.Config{
        DataFileSize:  ybc.SizeT(10240),
        MaxItemsCount: ybc.SizeT(100),
        IndexFile:     "foo.idx",
        DataFile:      "foo.dat",
    }
    cache, err := cfg.OpenCache(true)
    if err != nil {
        panic(err)
    }

    b, err := json.Marshal(123)
    if err != nil {
        panic(err)
    }

    if err = cache.Set([]byte("key"), b, time.Hour); err != nil {
        panic(err)
    }
}

gives

[adam@scopuli ~]$ go run test.go 
panic: runtime error: cgo argument has Go pointer to Go pointer

goroutine 1 [running]:
panic(0x5123a0, 0xc82000a430)
        /usr/lib/go/src/runtime/panic.go:464 +0x3e6
github.com/valyala/ybc/bindings/go/ybc.(*Cache).Set(0xc82000e2e0, 0xc82000a410, 0x3, 0x8, 0xc820082024, 0x3, 0x40, 0x34630b8a000, 0x0, 0x0)
        /home/adam/go/src/github.com/valyala/ybc/bindings/go/ybc/ybc.go:457 +0x385
main.main()
        /home/adam/test.go:26 +0x226
exit status 2

However, this works fine:

cache.Set([]byte("key"), []byte(string(b)), time.Hour);

Running:

go version go1.6 linux/amd64

and ybc 82bc72dc617945514a43056c92c023f65e045ae6

vektah avatar Apr 14 '16 09:04 vektah

This looks like a bug in Go runtime. Will try narrowing down it and posting to Go issue tracker.

valyala avatar Apr 15 '16 15:04 valyala

As a temporary workaround you can use GODEBUG="cgocheck=0" environment variable for disabling cgo check. See Environment Variables chapter in runtime package for details.

valyala avatar Apr 15 '16 16:04 valyala

Minimized it to:

package main

// static void foo(void *p) {}
import "C"

import (
    "encoding/json"
    "unsafe"
)

func main() {
    b, err := json.Marshal(123)
    if err != nil {
        panic(err)
    }
    p := unsafe.Pointer(&b[0])
    C.foo(p)
}

valyala avatar Apr 15 '16 16:04 valyala

There is another workaround mentioned in the linked Go issue:

What is messing up is that encoding/json uses a 64 byte buffer in a larger struct, and if the encoding requires 64 bytes or fewer than the resulting pointer is into that struct. So one workaround is

if len(b) <= 64 {
    b = append([]byte(nil), b...)
}
if err = cache.Set([]byte("key"), b, time.Hour); err != nil {
        panic(err)
}

valyala avatar Apr 16 '16 13:04 valyala