diff --git a/config/config.go b/config/config.go index f01ddcfb4..fec9eb0b1 100644 --- a/config/config.go +++ b/config/config.go @@ -8,7 +8,6 @@ import ( "sync" "launchpad.net/goyaml" - ) type Config struct { @@ -41,13 +40,13 @@ func GetString(key string) string { } func GetStringArray(key string) []string { - res,_:= config.GetStringArray(key) + res, _ := config.GetStringArray(key) return res } -func GetStringArrayDefault(key string,def []string) []string { - res,ok := config.GetStringArray(key) +func GetStringArrayDefault(key string, def []string) []string { + res, ok := config.GetStringArray(key) - if ! ok{ + if !ok { return def } return res @@ -61,7 +60,6 @@ func GetIntDefault(key string, default_value int) int { return config.GetIntDefault(key, default_value) } - func NewConfig(filename string) *Config { self := Config{} self.config = make(map[string]interface{}) @@ -85,13 +83,11 @@ func (self *Config) load() error { } data, err := ioutil.ReadFile(config_file) if err != nil { - return errors.New("Problem with config file: " + err.Error()) } - - err=goyaml.Unmarshal(data, self.config) - if err != nil{ - println(err.Error()) + err = goyaml.Unmarshal(data, self.config) + if err != nil { + println(err.Error()) } self.loaded = true @@ -134,7 +130,6 @@ func (self *Config) GetIntDefault(key string, default_value int) int { return default_value } - func (self *Config) GetStringDefault(key string, default_value string) string { value, ok := self.GetSafe(key) if ok { @@ -146,7 +141,6 @@ func (self *Config) GetStringDefault(key string, default_value string) string { return default_value } - func (self *Config) GetString(key string) string { value, ok := self.GetSafe(key) if ok { @@ -158,18 +152,14 @@ func (self *Config) GetString(key string) string { return "" } - - -func (self *Config) GetStringArray(key string) ([]string,bool){ +func (self *Config) GetStringArray(key string) ([]string, bool) { value, ok := self.GetSafe(key) - if ok { var results []string - for _,v:= range value.([]interface{}){ - results=append(results,v.(string)) + for _, v := range value.([]interface{}) { + results = append(results, v.(string)) } - return results,ok + return results, ok } - return []string{},ok + return []string{}, ok } - diff --git a/core/etcd.go b/core/etcd.go index 0dd72002c..9a6b7951c 100644 --- a/core/etcd.go +++ b/core/etcd.go @@ -105,7 +105,7 @@ func getLightestProcess(m map[string]int) (Pair, error) { } func (self *TopologyMapper) MakeFragments(db string, slice_int int) error { - frames_to_create := config.GetStringArrayDefault("supported_frames", []string{"b.n", "l.n", "t.t", "d"}) + frames_to_create := config.GetStringArrayDefault("supported_frames", []string{"default"}) for _, frame := range frames_to_create { err := self.AllocateFragment(db, frame, slice_int) if err != nil { diff --git a/db/topology.go b/db/topology.go index 553362c04..ed4cfb4c6 100644 --- a/db/topology.go +++ b/db/topology.go @@ -4,13 +4,14 @@ import ( "errors" "fmt" "log" + "pilosa/config" "pilosa/util" "sync" - "github.com/stathat/consistent" ) var FrameDoesNotExistError = errors.New("Frame does not exist.") +var InvalidFrameError = errors.New("Invalid frame.") var SliceDoesNotExistError = errors.New("Slice does not exist.") var FragmentDoesNotExistError = errors.New("Fragment does not exist.") var FrameSliceIntersectDoesNotExistError = errors.New("FrameSliceIntersect does not exist.") @@ -159,6 +160,20 @@ func (c *Cluster) GetOrCreateDatabase(name string) *Database { return c.addDatabase(name) } +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} + +func (d *Database) IsValidFrame(name string) bool { + supported_frames := config.GetStringArrayDefault("supported_frames", []string{"default"}) + return stringInSlice(name, supported_frames) +} + // Count the number of slices in a database func (d *Database) NumSlices() (int, error) { if len(d.slices) < 1 { @@ -177,6 +192,10 @@ type Frame struct { // Get a frame from a database func (d *Database) getFrame(name string) (*Frame, error) { + // should we check here for supported frames? + if !d.IsValidFrame(name) { + return nil, InvalidFrameError + } for _, frame := range d.frames { if frame.name == name { return frame, nil diff --git a/executor/executor.go b/executor/executor.go index 966895aff..44f6c2d67 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -73,8 +73,9 @@ func (self *Executor) runQuery(database *db.Database, qry *query.Query) error { query_plan, err := query.QueryPlanForQuery(database, qry, &destination) if err != nil { - obj, found := err.(*query.FragmentNotFound) - if found { + switch obj := err.(type) { + //case *query.InvalidFrame: + case *query.FragmentNotFound: self.service.TopologyMapper.MakeFragments(obj.Db, obj.Slice) } self.service.Hold.Set(qry.Id, err, 30) diff --git a/query/planner.go b/query/planner.go index 82470a75d..0021e3fb9 100644 --- a/query/planner.go +++ b/query/planner.go @@ -17,6 +17,26 @@ type PortableQueryStep interface { GetLocation() *db.Location } +/////////////////////////////////////////////////////////////////////////////////////////////////// +// ERRORS +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// Invalid Frame +type InvalidFrame struct { + Db string + Frame string + Retry bool +} + +func NewInvalidFrame(db string, frame string) *InvalidFrame { + return &InvalidFrame{db, frame, false} +} + +func (self *InvalidFrame) Error() string { + return fmt.Sprintf("Invalid Frame: %s:%s", self.Db, self.Frame) +} + +// Fragment Not Found type FragmentNotFound struct { Db string Frame string @@ -24,7 +44,7 @@ type FragmentNotFound struct { Retry bool } -func NewFragmentNotFound(db, frame string, slice int) *FragmentNotFound { +func NewFragmentNotFound(db string, frame string, slice int) *FragmentNotFound { return &FragmentNotFound{db, frame, slice, true} } @@ -269,15 +289,18 @@ type SetQueryTree struct { // Uses consistent hashing function to select node containing data for GET operation func (qt *SetQueryTree) getLocation(d *db.Database) (*db.Location, error) { + // check here for supported frames + if !d.IsValidFrame(qt.bitmap.FrameType) { + return nil, NewInvalidFrame(d.Name, qt.bitmap.FrameType) + } slice, err := d.GetSliceForProfile(qt.profile_id) if err != nil { - //I should check GetFragmentForBitmap for possible errors but for now i'll just hardcode - return nil, NewFragmentNotFound(d.Name, "b.n", db.GetSlice(qt.profile_id)) + return nil, NewFragmentNotFound(d.Name, qt.bitmap.FrameType, db.GetSlice(qt.profile_id)) } fragment, err := d.GetFragmentForBitmap(slice, qt.bitmap) if err != nil { log.Println("NOT FOUND:", slice, qt.bitmap) - return nil, err + return nil, NewFragmentNotFound(d.Name, qt.bitmap.FrameType, db.GetSlice(qt.profile_id)) } return fragment.GetLocation(), nil }