Skip to content

Commit

Permalink
Various fixes related to ElektraInitiative/libelektra#3555
Browse files Browse the repository at this point in the history
  • Loading branch information
kodebach committed Dec 10, 2020
1 parent 330ea4c commit abb90aa
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 73 deletions.
29 changes: 29 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Created by https://www.toptal.com/developers/gitignore/api/go,vscode
# Edit at https://www.toptal.com/developers/gitignore?templates=go,vscode

### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

### Go Patch ###
/vendor/
/Godeps/

### vscode ###
.vscode
*.code-workspace

# End of https://www.toptal.com/developers/gitignore/api/go,vscode
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ First _go get_ the package like you are used to with Go.
Here is an example how you can use Elektra in your Go application.
Before you start create a key via the `kdb` command-line tool:

`kdb set user/go/elektra 'Hello World!'`
`kdb set user:/go/elektra 'Hello World!'`

Save the following code to a file, e.g.: `elektra.go` and run it via

Expand Down Expand Up @@ -97,7 +97,7 @@ func main() {
foundKey := ks.LookupByName(keyName)

if foundKey == nil {
fmt.Printf("Key %q not found, please run the following command to create it:\nkdb set user/go/elektra 'Hello World!'\n", keyName)
fmt.Printf("Key %q not found, please run the following command to create it:\nkdb set user:/go/elektra 'Hello World!'\n", keyName)
} else {
value := foundKey.Value()
fmt.Printf("Value of %q is: %s\n", keyName, value)
Expand Down
2 changes: 1 addition & 1 deletion kdb/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func setupTestData(b *testing.B, count int) *CKeySet {
keys := make([]Key, count)

for n := 0; n < count; n++ {
k, err := NewKey(fmt.Sprintf("proc/tests/go/elektra/benchmark/iterator/callback/%08d", n))
k, err := NewKey(fmt.Sprintf("proc:/tests/go/elektra/benchmark/iterator/callback/%08d", n))
Checkf(b, err, "kdb.NewKey() failed: %v", err)

keys[n] = k
Expand Down
10 changes: 5 additions & 5 deletions kdb/kdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func New() KDB {
// Open creates a handle to the kdb library,
// this is mandatory to Get / Set Keys.
func (e *KdbC) Open() error {
key, err := newKey("")
key, err := newKey("/")

if err != nil {
return err
Expand All @@ -50,7 +50,7 @@ func (e *KdbC) Open() error {

// Close closes the kdb handle.
func (e *KdbC) Close() error {
key, err := newKey("")
key, err := newKey("/")

if err != nil {
return err
Expand Down Expand Up @@ -116,11 +116,11 @@ func (e *KdbC) Set(keySet KeySet, parentKey Key) (bool, error) {
}

// Version `Get`s the current version of Elektra from
// the "system/elektra/version/constants/KDB_VERSION" key
// the "system:/elektra/version/constants/KDB_VERSION" key
// in the format Major.Minor.Micro, be aware that this can
// lead to unexpected state-changes.
func (e *KdbC) Version() (string, error) {
k, err := NewKey("system/elektra/version")
k, err := NewKey("system:/elektra/version")

if err != nil {
return "", err
Expand All @@ -130,7 +130,7 @@ func (e *KdbC) Version() (string, error) {

_, err = e.Get(ks, k)

versionKey := ks.LookupByName("system/elektra/version/constants/KDB_VERSION")
versionKey := ks.LookupByName("system:/elektra/version/constants/KDB_VERSION")
version := versionKey.String()

return version, nil
Expand Down
14 changes: 7 additions & 7 deletions kdb/kdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestSet(t *testing.T) {
Checkf(t, err, "kdb.Open() failed: %v", err)

ks := elektra.NewKeySet()
key, _ := elektra.NewKey("user/tests/go/elektra/set")
key, _ := elektra.NewKey("user:/tests/go/elektra/set")
_, _ = kdb.Get(ks, key)

ks.AppendKey(key)
Expand All @@ -37,7 +37,7 @@ func TestSet(t *testing.T) {

func TestRemoveKey(t *testing.T) {
kdb := elektra.New()
namespace := "user/tests/go/elektra/removekey"
namespace := "user:/tests/go/elektra/removekey"

parentKey, err := elektra.NewKey(namespace)
Check(t, err, "could not create parent Key")
Expand Down Expand Up @@ -102,11 +102,11 @@ func TestConflict(t *testing.T) {
ks1 := elektra.NewKeySet()
ks2 := elektra.NewKeySet()

rootKey1, _ := elektra.NewKey("user/tests/go/elektra/conflict")
rootKey2, _ := elektra.NewKey("user/tests/go/elektra/conflict")
firstKey, _ := elektra.NewKey("user/tests/go/elektra/conflict/first")
secondKey, _ := elektra.NewKey("user/tests/go/elektra/conflict/second")
conflictKey, _ := elektra.NewKey("user/tests/go/elektra/conflict/second")
rootKey1, _ := elektra.NewKey("user:/tests/go/elektra/conflict")
rootKey2, _ := elektra.NewKey("user:/tests/go/elektra/conflict")
firstKey, _ := elektra.NewKey("user:/tests/go/elektra/conflict/first")
secondKey, _ := elektra.NewKey("user:/tests/go/elektra/conflict/second")
conflictKey, _ := elektra.NewKey("user:/tests/go/elektra/conflict/second")

_ = kdb1.Open()
defer kdb1.Close()
Expand Down
55 changes: 32 additions & 23 deletions kdb/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ package kdb
// #include <kdb.h>
// #include <stdlib.h>
//
// static Key * keyNewEmptyWrapper() {
// return keyNew(0, KEY_END);
// }
//
// static Key * keyNewWrapper(char* k) {
// return keyNew(k, KEY_END);
Expand All @@ -22,10 +19,24 @@ import (
"unsafe"
)

type ElektraNamepace byte

const (
KEY_NS_NONE ElektraNamepace = C.KEY_NS_NONE
KEY_NS_CASCADING ElektraNamepace = C.KEY_NS_CASCADING
KEY_NS_META ElektraNamepace = C.KEY_NS_META
KEY_NS_SPEC ElektraNamepace = C.KEY_NS_SPEC
KEY_NS_PROC ElektraNamepace = C.KEY_NS_PROC
KEY_NS_DIR ElektraNamepace = C.KEY_NS_DIR
KEY_NS_USER ElektraNamepace = C.KEY_NS_USER
KEY_NS_SYSTEM ElektraNamepace = C.KEY_NS_SYSTEM
KEY_NS_DEFAULT ElektraNamepace = C.KEY_NS_DEFAULT
)

// Key is the wrapper around the Elektra Key.
type Key interface {
Name() string
Namespace() string
Namespace() ElektraNamepace
BaseName() string

String() string
Expand Down Expand Up @@ -70,7 +81,7 @@ func newKey(name string, value ...interface{}) (*CKey, error) {
defer C.free(unsafe.Pointer(n))

if name == "" {
key = wrapKey(C.keyNewEmptyWrapper())
return nil, errors.New("unsupported key name")
} else if len(value) > 0 {
switch v := value[0].(type) {
case string:
Expand All @@ -85,7 +96,7 @@ func newKey(name string, value ...interface{}) (*CKey, error) {
}

if key == nil {
return nil, errors.New("could not create key")
return nil, errors.New("could not create key (check the key name)")
}

return key, nil
Expand Down Expand Up @@ -123,8 +134,8 @@ func toCKey(key Key) (*CKey, error) {

// BaseName returns the basename of the Key.
// Some examples:
// - BaseName of system/some/keyname is keyname
// - BaseName of "user/tmp/some key" is "some key"
// - BaseName of system:/some/keyname is keyname
// - BaseName of "user:/tmp/some key" is "some key"
func (k *CKey) BaseName() string {
name := C.keyBaseName(k.Ptr)

Expand Down Expand Up @@ -288,7 +299,7 @@ func (k *CKey) MetaMap() map[string]string {
m := make(map[string]string)

for key := dup.NextMeta(); key != nil; key = dup.NextMeta() {
m[key.Name()] = key.String()
m[strings.TrimPrefix(key.Name(), "meta:/")] = key.String()
}

return m
Expand Down Expand Up @@ -349,15 +360,8 @@ func (k *CKey) Compare(other Key) int {
}

// Namespace returns the namespace of a Key.
func (k *CKey) Namespace() string {
name := k.Name()
index := strings.Index(name, "/")

if index < 0 {
return ""
}

return name[:index]
func (k *CKey) Namespace() ElektraNamepace {
return ElektraNamepace(C.keyGetNamespace(k.Ptr))
}

func nameWithoutNamespace(key Key) string {
Expand All @@ -383,16 +387,21 @@ func CommonKeyName(key1, key2 Key) string {
return key1Name
}

if key1.Namespace() != key2.Namespace() {
key1Name = nameWithoutNamespace(key1)
key2Name = nameWithoutNamespace(key2)
key1Path := nameWithoutNamespace(key1)
key2Path := nameWithoutNamespace(key2)

ns := "/"
if key1.Namespace() == key2.Namespace() {
ns = key1Name[:strings.Index(key1Name, "/")] + "/"
} else if key1Path[2] != key2Path[2] {
return ""
}

index := 0
k1Parts, k2Parts := strings.Split(key1Name, "/"), strings.Split(key2Name, "/")
k1Parts, k2Parts := strings.Split(key1Path[1:], "/"), strings.Split(key2Path[1:], "/")

for ; index < len(k1Parts) && index < len(k2Parts) && k1Parts[index] == k2Parts[index]; index++ {
}

return strings.Join(k1Parts[:index], "/")
return ns + strings.Join(k1Parts[:index], "/")
}
42 changes: 21 additions & 21 deletions kdb/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (
)

func TestName(t *testing.T) {
firstName := "user/tests/go/elektra/name/1"
firstName := "user:/tests/go/elektra/name/1"
k, err := elektra.NewKey(firstName)

Check(t, err, "could not create key")
Assert(t, k.Name() == firstName, "wrong key name")

secondName := "user/tests/go/elektra/name/2"
secondName := "user:/tests/go/elektra/name/2"
err = k.SetName(secondName)

Check(t, err, "could not set key name")
Expand All @@ -27,7 +27,7 @@ func TestName(t *testing.T) {
func TestString(t *testing.T) {
testValue := "Hello World"

k, err := elektra.NewKey("user/tests/go/elektra/string", testValue)
k, err := elektra.NewKey("user:/tests/go/elektra/string", testValue)
Check(t, err, "could not create key")

val := k.String()
Expand All @@ -39,10 +39,10 @@ var bytesTests = []struct {
key2 string
expected string
}{
{"user/foo/bar", "user/foo/bar2", "user/foo"},
{"proc/foo/bar", "user/foo/bar", "/foo/bar"},
{"user/foo/bar", "user/bar/foo", "user"},
{"proc/bar/foo", "user/foo/bar", ""},
{"user:/foo/bar", "user:/foo/bar2", "user:/foo"},
{"proc:/foo/bar", "user:/foo/bar", "/foo/bar"},
{"user:/foo/bar", "user:/bar/foo", "user:/"},
{"proc:/bar/foo", "user:/foo/bar", ""},
}

func TestBytes(t *testing.T) {
Expand All @@ -55,7 +55,7 @@ func TestBytes(t *testing.T) {
rand.Read(values[0])

for testcase, want := range values {
k, err := elektra.NewKey("user/tests/go/elektra/bytes")
k, err := elektra.NewKey("user:/tests/go/elektra/bytes")
Check(t, err, "could not create key")

err = k.SetBytes(want)
Expand All @@ -67,7 +67,7 @@ func TestBytes(t *testing.T) {
}

func TestMeta(t *testing.T) {
k, err := elektra.NewKey("user/tests/go/elektra/meta", "Hello World")
k, err := elektra.NewKey("user:/tests/go/elektra/meta", "Hello World")
Check(t, err, "could not create key")

err = k.SetMeta("meta", "value")
Expand Down Expand Up @@ -98,7 +98,7 @@ func TestMetaMap(t *testing.T) {
"baz": "baz",
}

key := keyWithMetaKeys(t, "user/tests/go/elektra/meta", keyValues)
key := keyWithMetaKeys(t, "user:/tests/go/elektra/meta", keyValues)

metaMap := key.MetaMap()

Expand All @@ -113,12 +113,12 @@ func TestMetaMap(t *testing.T) {

func TestMetaSlice(t *testing.T) {
keyValues := map[string]string{
"foo": "foo",
"bar": "bar",
"baz": "baz",
"meta:/foo": "foo",
"meta:/bar": "bar",
"meta:/baz": "baz",
}

key := keyWithMetaKeys(t, "user/tests/go/elektra/meta", keyValues)
key := keyWithMetaKeys(t, "user:/tests/go/elektra/meta", keyValues)

metaSlice := key.MetaSlice()

Expand All @@ -132,15 +132,15 @@ func TestMetaSlice(t *testing.T) {
}

func TestNamespace(t *testing.T) {
key, _ := elektra.NewKey("user/tests/go/elektra/namespace")
key, _ := elektra.NewKey("user:/tests/go/elektra/namespace")

expected := "user"
expected := elektra.KEY_NS_USER
namespace := key.Namespace()
Assertf(t, namespace == expected, "Namespace be %q but is %q", expected, namespace)

key, _ = elektra.NewKey("/go-elektra/namespace")

expected = ""
expected = elektra.KEY_NS_CASCADING
namespace = key.Namespace()
Assertf(t, namespace == expected, "Namespace be %q but is %q", expected, namespace)
}
Expand All @@ -150,10 +150,10 @@ var commonKeyNameTests = []struct {
key2 string
expected string
}{
{"user/foo/bar", "user/foo/bar2", "user/foo"},
{"proc/foo/bar", "user/foo/bar", "/foo/bar"},
{"user/foo/bar", "user/bar/foo", "user"},
{"proc/bar/foo", "user/foo/bar", ""},
{"user:/foo/bar", "user:/foo/bar2", "user:/foo"},
{"proc:/foo/bar", "user:/foo/bar", "/foo/bar"},
{"user:/foo/bar", "user:/bar/foo", "user:/"},
{"proc:/bar/foo", "user:/foo/bar", ""},
}

func TestCommonKeyName(t *testing.T) {
Expand Down
Loading

0 comments on commit abb90aa

Please sign in to comment.