create input-definiton

This commit is contained in:
Linh Vo 2017-06-08 14:23:46 -05:00
parent f066d1e125
commit c80bedb402
7 changed files with 1515 additions and 57 deletions

View file

@ -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"`
}

View file

@ -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
View 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

View file

@ -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 {

View file

@ -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,

View file

@ -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")