mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
use extensions through build tags
This commit is contained in:
parent
179fb910f7
commit
f51c2dbc42
5 changed files with 78 additions and 62 deletions
1
Makefile
1
Makefile
|
|
@ -16,6 +16,7 @@ RELEASE_ENABLED = $(subst 0,,$(RELEASE))
|
|||
BUILD_TAGS += $(if $(ENTERPRISE_ENABLED),enterprise)
|
||||
BUILD_TAGS += $(if $(RELEASE_ENABLED),release)
|
||||
BUILD_TAGS += shardwidth$(SHARD_WIDTH)
|
||||
BUILD_TAGS += $(foreach p,$(PLUGINS),plugin$(p))
|
||||
define LICENSE_HASH_CODE
|
||||
head -13 $1 | sed -e 's/Copyright 20[0-9][0-9]/Copyright 20XX/g' | shasum | cut -f 1 -d " "
|
||||
endef
|
||||
|
|
|
|||
25
ext/ext.go
25
ext/ext.go
|
|
@ -38,6 +38,8 @@
|
|||
// case, no ops are registered.
|
||||
package ext
|
||||
|
||||
import "sync"
|
||||
|
||||
// The Bitmap type represents a Pilosa bitmap, and is used for bitmap
|
||||
// operations.
|
||||
type Bitmap interface {
|
||||
|
|
@ -236,3 +238,26 @@ type ExtensionInfo struct {
|
|||
License string // License info.
|
||||
BitmapOps []BitmapOp // List of provided ops.
|
||||
}
|
||||
|
||||
var extMu sync.Mutex
|
||||
|
||||
var knownExtensions []*ExtensionInfo
|
||||
var newExtensions []*ExtensionInfo
|
||||
|
||||
// RegisterExtension tells the extension system about a new extension.
|
||||
func RegisterExtension(ext *ExtensionInfo) {
|
||||
extMu.Lock()
|
||||
defer extMu.Unlock()
|
||||
newExtensions = append(newExtensions, ext)
|
||||
}
|
||||
|
||||
// NewExtentsions returns extensions that have been registered, but not previously
|
||||
// returned by Newextensions.
|
||||
func NewExtensions() []*ExtensionInfo {
|
||||
extMu.Lock()
|
||||
defer extMu.Unlock()
|
||||
knownExtensions = append(knownExtensions, newExtensions...)
|
||||
ret := newExtensions
|
||||
newExtensions = nil
|
||||
return ret
|
||||
}
|
||||
|
|
|
|||
21
ext/extensions/distinct.go
Normal file
21
ext/extensions/distinct.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2019 Pilosa Corp.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
// +build plugindistinct
|
||||
|
||||
package extensions
|
||||
|
||||
import (
|
||||
_ "github.com/molecula/extensions/distinct"
|
||||
)
|
||||
18
ext/extensions/dummy.go
Normal file
18
ext/extensions/dummy.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2019 Pilosa Corp.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
// This package contains only things which are conditional on build
|
||||
// tags.
|
||||
|
||||
package extensions
|
||||
75
server.go
75
server.go
|
|
@ -17,12 +17,10 @@ package pilosa
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -30,6 +28,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/pilosa/pilosa/v2/ext"
|
||||
// extensions pulls in some extensions depending on build tags
|
||||
_ "github.com/pilosa/pilosa/v2/ext/extensions"
|
||||
"github.com/pilosa/pilosa/v2/logger"
|
||||
"github.com/pilosa/pilosa/v2/pql"
|
||||
"github.com/pilosa/pilosa/v2/roaring"
|
||||
|
|
@ -341,8 +341,6 @@ func NewServer(opts ...ServerOption) (*Server, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.extensionPath = filepath.Join(path, ".extensions")
|
||||
|
||||
s.holder.Path = path
|
||||
// s.holder.translateFile.Path = filepath.Join(path, ".keys")
|
||||
s.holder.Logger = s.logger
|
||||
|
|
@ -383,7 +381,7 @@ func NewServer(opts ...ServerOption) (*Server, error) {
|
|||
s.cluster.broadcaster = s
|
||||
s.cluster.maxWritesPerRequest = s.maxWritesPerRequest
|
||||
s.holder.broadcaster = s
|
||||
err = s.loadPlugins()
|
||||
err = s.loadExtensions()
|
||||
if err != nil {
|
||||
s.logger.Printf("not all plugins loaded successfully")
|
||||
}
|
||||
|
|
@ -420,67 +418,20 @@ func (s *Server) InternalClient() InternalClient {
|
|||
return s.defaultClient
|
||||
}
|
||||
|
||||
func (s *Server) loadPlugins() error {
|
||||
var anyError error
|
||||
dir, err := os.Open(s.extensionPath)
|
||||
if err != nil {
|
||||
// don't complain about it not existing, that's fine.
|
||||
if os.IsNotExist(err) {
|
||||
s.logger.Printf("extension interface v0: no extensions directory.")
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "opening extension path:")
|
||||
}
|
||||
defer dir.Close()
|
||||
for files, err := dir.Readdir(64); err != io.EOF; files, err = dir.Readdir(64) {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "searching extension directory:")
|
||||
}
|
||||
for _, file := range files {
|
||||
name := file.Name()
|
||||
// only .so files are likely plugins.
|
||||
if !strings.HasSuffix(name, ".so") {
|
||||
continue
|
||||
}
|
||||
// only regular files are candidates for loading.
|
||||
mode := file.Mode()
|
||||
if !mode.IsRegular() {
|
||||
s.logger.Printf("extension file '%s' is not a regular file", name)
|
||||
continue
|
||||
}
|
||||
err = s.loadPlugin(name)
|
||||
if err != nil {
|
||||
s.logger.Printf("loading extension %s: %v", name, err)
|
||||
anyError = err
|
||||
}
|
||||
func (s *Server) loadExtensions() error {
|
||||
exts := ext.NewExtensions()
|
||||
var lastError error
|
||||
for _, extension := range exts {
|
||||
if err := s.loadExtension(extension); err != nil {
|
||||
lastError = err
|
||||
}
|
||||
}
|
||||
return anyError
|
||||
return lastError
|
||||
}
|
||||
|
||||
func (s *Server) loadPlugin(name string) error {
|
||||
path := filepath.Join(s.extensionPath, name)
|
||||
p, err := plugin.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pluginExtInfo, err := p.Lookup("ExtensionInfo")
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: no ExtensionInfo found", name)
|
||||
}
|
||||
extInfoFunc, ok := pluginExtInfo.(func(string) (*ext.ExtensionInfo, error))
|
||||
if !ok {
|
||||
return fmt.Errorf("%s: unexpected %T instead of ExtensionInfo object", name, pluginExtInfo)
|
||||
}
|
||||
extInfo, err := extInfoFunc("v0")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, name)
|
||||
}
|
||||
if extInfo == nil {
|
||||
return fmt.Errorf("%s: nil ExtensionInfo", name)
|
||||
}
|
||||
func (s *Server) loadExtension(extInfo *ext.ExtensionInfo) error {
|
||||
if extInfo.ExtensionAPI != "v0" {
|
||||
return fmt.Errorf("%s: unsupported extension API %s", name, extInfo.ExtensionAPI)
|
||||
return fmt.Errorf("%s: unsupported extension API %s", extInfo.Name, extInfo.ExtensionAPI)
|
||||
}
|
||||
s.extensions = append(s.extensions, extInfo)
|
||||
bitmapOps := extInfo.BitmapOps
|
||||
|
|
@ -500,7 +451,7 @@ func (s *Server) loadPlugin(name string) error {
|
|||
unknownOps++
|
||||
}
|
||||
}
|
||||
err = s.executor.registerOps(bitmapOps)
|
||||
err := s.executor.registerOps(bitmapOps)
|
||||
if err != nil {
|
||||
s.logger.Printf("warning: extension registration failed: %v", err)
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue