mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 00:55:55 +00:00
create input-definiton
This commit is contained in:
parent
f066d1e125
commit
c80bedb402
7 changed files with 1515 additions and 57 deletions
61
handler.go
61
handler.go
|
|
@ -129,6 +129,10 @@ func NewRouter(handler *Handler) *mux.Router {
|
|||
// For now we just do it for the most commonly used handler, /query
|
||||
router.HandleFunc("/index/{index}/query", handler.methodNotAllowedHandler).Methods("GET")
|
||||
|
||||
router.HandleFunc("/index/{index}/input-definition/{input-definition}", handler.handleGetDefinition).Methods("GET")
|
||||
router.HandleFunc("/index/{index}/input-definition/{input-definition}", handler.handlePostDefinition).Methods("POST")
|
||||
router.HandleFunc("/index/{index}input-definition/{input-definition}", handler.handleDeleteDefinition).Methods("DELETE")
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
|
|
@ -1495,3 +1499,60 @@ func errorString(err error) string {
|
|||
}
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
func (h *Handler) handlePostDefinition(w http.ResponseWriter, r *http.Request) {
|
||||
indexName := mux.Vars(r)["index"]
|
||||
inputDefName := mux.Vars(r)["input-definition"]
|
||||
|
||||
// Decode request.
|
||||
var req postInputDefinition
|
||||
err := json.NewDecoder(r.Body).Decode(&req)
|
||||
if err == io.EOF {
|
||||
// If no data was provided (EOF), we still create the frame
|
||||
// with default values.
|
||||
} else if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
fmt.Println(req)
|
||||
|
||||
// Find index.
|
||||
index := h.Holder.Index(indexName)
|
||||
if index == nil {
|
||||
http.Error(w, ErrIndexNotFound.Error(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Create InputDefinition.
|
||||
_, err = index.CreateInputDefinition(inputDefName, req.Frames, req.Fields)
|
||||
if err == ErrInputDefinitionExists {
|
||||
http.Error(w, err.Error(), http.StatusConflict)
|
||||
return
|
||||
} else if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
//err = h.Broadcaster.SendSync(
|
||||
// &internal.CreateInputDefinitionMessage{
|
||||
// Index: indexName,
|
||||
// InputDefinition: inputDefName,
|
||||
// Meta: req.Options.Encode(),
|
||||
// })
|
||||
//if err != nil {
|
||||
// h.logger().Printf("problem sending CreateFrame message: %s", err)
|
||||
//}
|
||||
}
|
||||
|
||||
func (h *Handler) handleGetDefinition(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
}
|
||||
|
||||
func (h *Handler) handleDeleteDefinition(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
}
|
||||
|
||||
type postInputDefinition struct {
|
||||
Frames []Frame `json:"frames,omitempty"`
|
||||
Fields []Field `json:"field,omitempty"`
|
||||
}
|
||||
|
|
|
|||
57
index.go
57
index.go
|
|
@ -57,6 +57,9 @@ type Index struct {
|
|||
// Column attribute storage and cache
|
||||
columnAttrStore *AttrStore
|
||||
|
||||
// InputDefinition by name
|
||||
inputDefinitions map[string]*InputDefinition
|
||||
|
||||
broadcaster Broadcaster
|
||||
Stats StatsClient
|
||||
|
||||
|
|
@ -71,9 +74,10 @@ func NewIndex(path, name string) (*Index, error) {
|
|||
}
|
||||
|
||||
return &Index{
|
||||
path: path,
|
||||
name: name,
|
||||
frames: make(map[string]*Frame),
|
||||
path: path,
|
||||
name: name,
|
||||
frames: make(map[string]*Frame),
|
||||
inputDefinitions: make(map[string]*InputDefinition),
|
||||
|
||||
remoteMaxSlice: 0,
|
||||
remoteMaxInverseSlice: 0,
|
||||
|
|
@ -327,6 +331,11 @@ func (i *Index) SetTimeQuantum(q TimeQuantum) error {
|
|||
// FramePath returns the path to a frame in the index.
|
||||
func (i *Index) FramePath(name string) string { return filepath.Join(i.path, name) }
|
||||
|
||||
// InputDefPath returns the path to a inputdefinition in the index.
|
||||
func (i *Index) InputDefPath(name string) string {
|
||||
return filepath.Join(i.path, ".input-definitions", name)
|
||||
}
|
||||
|
||||
// Frame returns a frame in the index by name.
|
||||
func (i *Index) Frame(name string) *Frame {
|
||||
i.mu.Lock()
|
||||
|
|
@ -362,6 +371,37 @@ func (i *Index) CreateFrame(name string, opt FrameOptions) (*Frame, error) {
|
|||
return i.createFrame(name, opt)
|
||||
}
|
||||
|
||||
// CreateInputDefinition creates a new input definition.
|
||||
func (i *Index) CreateInputDefinition(name string, frames []Frame, field []Field) (*InputDefinition, error) {
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
|
||||
// Ensure frame doesn't already exist.
|
||||
if i.inputDefinitions[name] != nil {
|
||||
return nil, ErrInputDefinitionExists
|
||||
}
|
||||
return i.createInputDefinition(name, frames, field)
|
||||
}
|
||||
|
||||
func (i *Index) createInputDefinition(name string, frames []Frame, field []Field) (*InputDefinition, error) {
|
||||
if name == "" {
|
||||
return nil, errors.New("input-definition name required")
|
||||
}
|
||||
|
||||
// Initialize frame.
|
||||
inputDef, err := i.newInputDefinition(i.InputDefPath(name), name)
|
||||
fmt.Println(inputDef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Open frame.
|
||||
if err := inputDef.Open(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i.inputDefinitions[name] = inputDef
|
||||
return inputDef, nil
|
||||
}
|
||||
|
||||
// CreateFrameIfNotExists creates a frame with the given options if it doesn't exist.
|
||||
func (i *Index) CreateFrameIfNotExists(name string, opt FrameOptions) (*Frame, error) {
|
||||
i.mu.Lock()
|
||||
|
|
@ -445,6 +485,17 @@ func (i *Index) newFrame(path, name string) (*Frame, error) {
|
|||
return f, nil
|
||||
}
|
||||
|
||||
func (i *Index) newInputDefinition(path, name string) (*InputDefinition, error) {
|
||||
f, err := NewInputDefinition(path, i.name, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.LogOutput = i.LogOutput
|
||||
f.Stats = i.Stats.WithTags(fmt.Sprintf("frame:%s", name))
|
||||
f.broadcaster = i.broadcaster
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// DeleteFrame removes a frame from the index.
|
||||
func (i *Index) DeleteFrame(name string) error {
|
||||
i.mu.Lock()
|
||||
|
|
|
|||
103
input_definition.go
Normal file
103
input_definition.go
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
package pilosa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
type InputDefinition struct {
|
||||
name string
|
||||
path string
|
||||
index string
|
||||
broadcaster Broadcaster
|
||||
Stats StatsClient
|
||||
LogOutput io.Writer
|
||||
}
|
||||
|
||||
func NewInputDefinition(path, index, name string) (*InputDefinition, error) {
|
||||
err := ValidateName(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputDefinition{
|
||||
path: path,
|
||||
index: index,
|
||||
name: name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Name returns the name of input definition was initialized with.
|
||||
func (i *InputDefinition) Name() string { return i.name }
|
||||
|
||||
// Index returns the index name of the input definition was initialized with.
|
||||
func (i *InputDefinition) Index() string { return i.index }
|
||||
|
||||
// Path returns the path of the input definition was initialized with.
|
||||
func (i *InputDefinition) Path() string { return i.path }
|
||||
|
||||
func (i *InputDefinition) Open() error {
|
||||
fmt.Println(i.path)
|
||||
if err := func() error {
|
||||
// Ensure the frame's path exists.
|
||||
if err := os.MkdirAll(i.path, 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//if err := i.loadMeta(); err != nil {
|
||||
// return err
|
||||
//}
|
||||
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// saveMeta writes meta data for the frame.
|
||||
//func (f *InputDefinition) saveMeta() error {
|
||||
// // Marshal metadata.
|
||||
// buf, err := proto.Marshal(&internal.InputDefinitionMeta{
|
||||
// Frames: f.
|
||||
// })
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// // Write to meta file.
|
||||
// if err := ioutil.WriteFile(filepath.Join(f.path, ".meta"), buf, 0666); err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// return nil
|
||||
//}
|
||||
|
||||
// FrameOptions represents options to set when initializing a frame.
|
||||
type InputDefinitionMeta struct {
|
||||
Frames []Frame `json:"frames,omitempty"`
|
||||
Fields []Field `json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
type Field struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
PrimaryKey bool `json:"primaryKey,omitempty"`
|
||||
Actions []Action `json:"action,omitempty"`
|
||||
}
|
||||
|
||||
type Action struct {
|
||||
Frame string `json:"frame,omitempty"`
|
||||
ValueDestination string `json:"valueDestination,omitempty"`
|
||||
ValueMap map[string]uint64 `json:"valueMap,omitempty"`
|
||||
RowID uint64 `json:"rowID,omitempty"`
|
||||
}
|
||||
|
||||
// Encode converts o into its internal representation.
|
||||
//func (o *InputDefinitionMeta) Encode() *internal.InputDefinitionMeta {
|
||||
// return &internal.InputDefinitionMeta{
|
||||
// Frames: o.Frames,
|
||||
// InputDefinitionFields: o.Fields,
|
||||
// }
|
||||
//}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -77,6 +77,37 @@ message Index {
|
|||
uint64 MaxSlice = 3;
|
||||
repeated Frame Frames = 4;
|
||||
repeated uint64 Slices = 5;
|
||||
repeated InputDefinition InputDefinitions = 6;
|
||||
}
|
||||
|
||||
message InputDefinition {
|
||||
string Name = 1;
|
||||
InputDefinitionMeta Meta = 2;
|
||||
}
|
||||
|
||||
message InputDefinitionMeta {
|
||||
repeated Frame Frames = 1;
|
||||
repeated InputDefinitionField InputDefinitionFields = 2;
|
||||
}
|
||||
|
||||
message InputDefinitionField {
|
||||
string Name = 1;
|
||||
bool PrimaryKey = 2;
|
||||
Action Meta = 3;
|
||||
}
|
||||
|
||||
message Action {
|
||||
string Frame = 1;
|
||||
string ValueDestination = 2;
|
||||
map<string, uint64> ValueMap = 3;
|
||||
uint64 RowID = 4;
|
||||
|
||||
}
|
||||
|
||||
message CreateInputDefinitionMessage {
|
||||
string Index = 1;
|
||||
string InputDefinition = 2;
|
||||
InputDefinitionMeta Meta = 3;
|
||||
}
|
||||
|
||||
message NodeStatus {
|
||||
|
|
|
|||
|
|
@ -2576,7 +2576,7 @@ func init() { proto.RegisterFile("public.proto", fileDescriptorPublic) }
|
|||
|
||||
var fileDescriptorPublic = []byte{
|
||||
// 576 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x54, 0x4b, 0x8e, 0xd3, 0x40,
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x4b, 0x8e, 0xd3, 0x40,
|
||||
0x10, 0xa5, 0x63, 0xe7, 0x57, 0xf9, 0x28, 0x6a, 0xf1, 0xb1, 0x10, 0x8a, 0x2c, 0x8b, 0x85, 0x57,
|
||||
0x19, 0x69, 0x38, 0x00, 0xc2, 0x49, 0x46, 0xb2, 0x10, 0x23, 0xa6, 0x33, 0xb0, 0xf7, 0xcc, 0xb4,
|
||||
0x06, 0x4b, 0xfe, 0xd1, 0xdd, 0x16, 0xe4, 0x00, 0xec, 0x91, 0xd8, 0x70, 0x03, 0x38, 0x0a, 0x4b,
|
||||
|
|
|
|||
11
pilosa.go
11
pilosa.go
|
|
@ -30,11 +30,12 @@ var (
|
|||
ErrIndexNotFound = errors.New("index not found")
|
||||
|
||||
// ErrFrameRequired is returned when no frame is specified.
|
||||
ErrFrameRequired = errors.New("frame required")
|
||||
ErrFrameExists = errors.New("frame already exists")
|
||||
ErrFrameNotFound = errors.New("frame not found")
|
||||
ErrFrameInverseDisabled = errors.New("frame inverse disabled")
|
||||
ErrColumnRowLabelEqual = errors.New("column and row labels cannot be equal")
|
||||
ErrFrameRequired = errors.New("frame required")
|
||||
ErrFrameExists = errors.New("frame already exists")
|
||||
ErrInputDefinitionExists = errors.New("input-definition already exists")
|
||||
ErrFrameNotFound = errors.New("frame not found")
|
||||
ErrFrameInverseDisabled = errors.New("frame inverse disabled")
|
||||
ErrColumnRowLabelEqual = errors.New("column and row labels cannot be equal")
|
||||
|
||||
ErrInvalidView = errors.New("invalid view")
|
||||
ErrInvalidCacheType = errors.New("invalid cache type")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue