Add basic Go Indexer bindings.
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/69b5681d Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/69b5681d Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/69b5681d Branch: refs/heads/master Commit: 69b5681d7041e4c37827f689dbdf509619e93886 Parents: 6e10881 Author: Marvin Humphrey <[email protected]> Authored: Sun Nov 16 22:06:58 2014 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Sun Mar 15 18:48:11 2015 -0700 ---------------------------------------------------------------------- go/lucy/index.go | 166 ++++++++++++++++++++++++++++++++++++++++++++++ go/lucy/lucy_test.go | 11 ++- 2 files changed, 176 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy/blob/69b5681d/go/lucy/index.go ---------------------------------------------------------------------- diff --git a/go/lucy/index.go b/go/lucy/index.go new file mode 100644 index 0000000..f0e0979 --- /dev/null +++ b/go/lucy/index.go @@ -0,0 +1,166 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lucy + +/* +#include "Lucy/Index/Indexer.h" +#include "Lucy/Index/IndexManager.h" +#include "Lucy/Document/Doc.h" +#include "Lucy/Plan/Schema.h" +#include "Clownfish/Hash.h" +#include "Clownfish/String.h" +#include "Clownfish/VArray.h" +#include "Clownfish/Err.h" +*/ +import "C" +import "fmt" +import "reflect" +import "runtime" +import "strings" +import "unsafe" +import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish" + +type Indexer struct { + ref *C.lucy_Indexer + fieldNames map[string]*clownfish.String +} + +type IndexManager struct { + ref *C.lucy_IndexManager +} + +type OpenIndexerArgs struct { + Schema *Schema + Index interface{} + Manager *IndexManager + Create bool + Truncate bool +} + +func OpenIndexer(args *OpenIndexerArgs) (obj *Indexer, err error) { + var schemaC *C.lucy_Schema = nil + if args.Schema != nil { + schemaC = args.Schema.ref + } + switch args.Index.(type) { + case string: + default: + panic("TODO: support Folder") + } + ixLoc := clownfish.NewString(args.Index.(string)) + var managerC *C.lucy_IndexManager = nil + if args.Manager != nil { + managerC = args.Manager.ref + } + var flags int32 + if args.Create { + flags = flags | int32(C.lucy_Indexer_CREATE) + } + if args.Truncate { + flags = flags | int32(C.lucy_Indexer_TRUNCATE) + } + err = clownfish.TrapErr(func() { + obj = &Indexer{ + C.lucy_Indexer_new(schemaC, (*C.cfish_Obj)(ixLoc.ToPtr()), + managerC, C.int32_t(flags)), + nil, + } + runtime.SetFinalizer(obj, (*Indexer).finalize) + }) + return obj, err +} + +func (obj *Indexer) finalize() { + obj.Close() +} + +func (obj *Indexer) Close() error { + // TODO: implement Close in core Lucy rather than bindings. + if obj.ref != nil { + C.cfish_dec_refcount(unsafe.Pointer(obj.ref)) + obj.ref = nil + } + return nil // TODO catch errors +} + +func (obj *Indexer) AddDoc(doc interface{}) error { + stockDoc := C.LUCY_Indexer_Get_Stock_Doc(obj.ref) + docFields := (*C.cfish_Hash)(C.LUCY_Doc_Get_Fields(stockDoc)) + C.CFISH_Hash_Clear(docFields) + + // TODO: Support map as doc in addition to struct as doc. + + // Get reflection value and type for the supplied struct. + var docValue reflect.Value + if reflect.ValueOf(doc).Kind() == reflect.Ptr { + temp := reflect.ValueOf(doc).Elem() + if temp.Kind() == reflect.Struct { + docValue = temp + } + } + if docValue == (reflect.Value{}) { + mess := fmt.Sprintf("Doc not struct pointer: %v", + reflect.TypeOf(doc)) + return clownfish.NewError(mess) + } + docType := docValue.Type() + + for i := 0; i < docValue.NumField(); i++ { + field := docType.Field(i).Name + value := docValue.Field(i).String() + fieldC := obj.findFieldC(field) + valueC := clownfish.NewString(value) + C.CFISH_Hash_Store(docFields, (*C.cfish_Obj)(fieldC.ToPtr()), + C.cfish_inc_refcount(valueC.ToPtr())) + } + + // TODO create an additional method AddDocWithBoost which allows the + // client to supply `boost`. + boost := 1.0 + err := clownfish.TrapErr(func() { + C.LUCY_Indexer_Add_Doc(obj.ref, stockDoc, C.float(boost)) + }) + + return err +} + +func (obj *Indexer) findFieldC(name string) *clownfish.String { + if obj.fieldNames == nil { + obj.fieldNames = make(map[string]*clownfish.String) + } + fieldC, ok := obj.fieldNames[name] + if !ok { + schema := C.LUCY_Indexer_Get_Schema(obj.ref) + fieldList := C.LUCY_Schema_All_Fields(schema) + defer C.cfish_dec_refcount(unsafe.Pointer(fieldList)) + for i := 0; i < int(C.CFISH_VA_Get_Size(fieldList)); i++ { + cfString := unsafe.Pointer(C.CFISH_VA_Fetch(fieldList, C.uint32_t(i))) + field := clownfish.CFStringToGo(cfString) + if strings.EqualFold(name, field) { + obj.fieldNames[name] = clownfish.NewString(field) + fieldC = obj.fieldNames[name] + } + } + } + return fieldC +} + +func (obj *Indexer) Commit() error { + return clownfish.TrapErr(func() { + C.LUCY_Indexer_Commit(obj.ref) + }) +} http://git-wip-us.apache.org/repos/asf/lucy/blob/69b5681d/go/lucy/lucy_test.go ---------------------------------------------------------------------- diff --git a/go/lucy/lucy_test.go b/go/lucy/lucy_test.go index 6a4c6d8..19b13bf 100644 --- a/go/lucy/lucy_test.go +++ b/go/lucy/lucy_test.go @@ -16,8 +16,17 @@ package lucy_test -import _ "git-wip-us.apache.org/repos/asf/lucy.git/go/lucy" +import "git-wip-us.apache.org/repos/asf/lucy.git/go/lucy" +import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish" import "testing" func TestStuff(t *testing.T) { + lucy.NewSchema() +} + +func TestOpenIndexer(t *testing.T) { + _, err := lucy.OpenIndexer(&lucy.OpenIndexerArgs{Index: "notalucyindex"}) + if _, ok := err.(*clownfish.Err); !ok { + t.Error("Didn't catch exception opening indexer") + } }
