mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 02:44:59 +00:00
* Remove MDS and replace it with Controller This commit removes the MDS layer (and package) and shifts Controller package into its place. * add pprof/fgprof to serverless http router --------- Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
179 lines
5.5 KiB
Go
179 lines
5.5 KiB
Go
package dax
|
|
|
|
// Directive contains the instructions, sent from the Controller, which a
|
|
// compute node is to follow. A Directive is typically JSON-encoded and POSTed
|
|
// to a compute node's `/directive` endpoint.
|
|
type Directive struct {
|
|
Address Address `json:"address"`
|
|
|
|
// Method describes how the compute node should handle the Directive. See
|
|
// the different constants of type DirectiveMethod for how this value is
|
|
// handled.
|
|
Method DirectiveMethod `json:"method"`
|
|
|
|
Tables []*QualifiedTable `json:"schema"`
|
|
|
|
ComputeRoles []ComputeRole `json:"compute-roles"`
|
|
TranslateRoles []TranslateRole `json:"translate-roles"`
|
|
|
|
Version uint64 `json:"version"`
|
|
}
|
|
|
|
type DirectiveVersion interface {
|
|
Increment(tx Transaction, delta uint64) (uint64, error)
|
|
}
|
|
|
|
// DirectiveMethod is used to tell the compute node how it should handle the
|
|
// Directive.
|
|
type DirectiveMethod string
|
|
|
|
const (
|
|
// DirectiveMethodDiff tells the compute node to diff the Directive with its
|
|
// local, cached Directive and only apply the differences.
|
|
DirectiveMethodDiff DirectiveMethod = "diff"
|
|
|
|
// DirectiveMethodReset tells the compute node to delete all of its existing
|
|
// data before applying the directive.
|
|
DirectiveMethodReset DirectiveMethod = "reset"
|
|
|
|
// DirectiveMethodSnapshot tells the compute node that the incoming
|
|
// Directive should only contain data version updates related to a snapshot
|
|
// request.
|
|
DirectiveMethodSnapshot DirectiveMethod = "snapshot"
|
|
)
|
|
|
|
// Table returns the ID'd table from the Directive's Tables list. If it's not
|
|
// found, it returns nil and a non-nil error. A nil error guarantees that the
|
|
// returned table is non-nil.
|
|
func (d *Directive) Table(qtid QualifiedTableID) (*QualifiedTable, error) {
|
|
for _, qtbl := range d.Tables {
|
|
// We can't do qtbl.QualifiedID() == qtid because the value of qtid.Name
|
|
// is empty and causes the equality check to fail. Hence the .Equals()
|
|
// method.
|
|
if qtbl.QualifiedID().Equals(qtid) {
|
|
return qtbl, nil
|
|
}
|
|
}
|
|
return nil, NewErrTableIDDoesNotExist(qtid)
|
|
}
|
|
|
|
// ComputeShards returns the list of shards, for the given table, for which this
|
|
// compute node is responsible. It assumes that the Directive does not contain
|
|
// more than one ComputeRole for the same table; in that case, we would need to
|
|
// return the union of Shards.
|
|
func (d *Directive) ComputeShards(tbl TableKey) ShardNums {
|
|
if d == nil || d.ComputeRoles == nil {
|
|
return nil
|
|
}
|
|
|
|
for _, cr := range d.ComputeRoles {
|
|
if cr.TableKey == tbl {
|
|
return cr.Shards
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ComputeShardsMap returns a map of table to shards. It assumes that the
|
|
// Directive does not contain more than one ComputeRole for the same table; in
|
|
// that case, we would need to return the union of Shards.
|
|
func (d *Directive) ComputeShardsMap() map[TableKey]ShardNums {
|
|
m := make(map[TableKey]ShardNums)
|
|
if d == nil || d.ComputeRoles == nil {
|
|
return m
|
|
}
|
|
|
|
for _, cr := range d.ComputeRoles {
|
|
m[cr.TableKey] = cr.Shards
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
// TranslatePartitions returns the list of partitions, for the given table, for
|
|
// which this translate node is responsible. It assumes that the Directive does
|
|
// not contain more than one TranslateRole for the same table; in that case, we
|
|
// would need to return the union of Shards.
|
|
func (d *Directive) TranslatePartitions(tbl TableKey) PartitionNums {
|
|
if d == nil || d.TranslateRoles == nil {
|
|
return PartitionNums{}
|
|
}
|
|
|
|
for _, tr := range d.TranslateRoles {
|
|
if tr.TableKey == tbl {
|
|
return tr.Partitions
|
|
}
|
|
}
|
|
return PartitionNums{}
|
|
}
|
|
|
|
// TranslatePartitionsMap returns a map of table to partitions. It assumes that
|
|
// the Directive does not contain more than one TranslateRole for the same
|
|
// table; in that case, we would need to return the union of Partitions.
|
|
func (d *Directive) TranslatePartitionsMap() map[TableKey]PartitionNums {
|
|
m := make(map[TableKey]PartitionNums)
|
|
if d == nil || d.TranslateRoles == nil {
|
|
return m
|
|
}
|
|
|
|
for _, tr := range d.TranslateRoles {
|
|
// Since we added FieldVersions to the TranslateRole, it's possible for
|
|
// a TranslateRole to have an empty Partitions list. In that case, we
|
|
// want to exclude that from the map.
|
|
if len(tr.Partitions) == 0 {
|
|
continue
|
|
}
|
|
m[tr.TableKey] = tr.Partitions
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
// TranslateFieldsMap returns a map of table to fields. It assumes that
|
|
// the Directive does not contain more than one TranslateRole for the same
|
|
// table; in that case, we would need to return the union of FieldValues.
|
|
func (d *Directive) TranslateFieldsMap() map[TableKey][]FieldName {
|
|
m := make(map[TableKey][]FieldName)
|
|
if d == nil || d.TranslateRoles == nil {
|
|
return m
|
|
}
|
|
|
|
for _, tr := range d.TranslateRoles {
|
|
if len(tr.Fields) == 0 {
|
|
continue
|
|
}
|
|
m[tr.TableKey] = tr.Fields
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
// IsEmpty tells whether a directive is assigning actual responsibilty
|
|
// to a node or not. If the directive does not assign responsibility
|
|
// for any shard or partition then it is considered empty. This is
|
|
// used to determine whether we can ignore an error received from
|
|
// applying this directive (an empty directive is often sent to a node
|
|
// which is already down).
|
|
func (d *Directive) IsEmpty() bool {
|
|
for _, role := range d.ComputeRoles {
|
|
if len(role.Shards) > 0 {
|
|
return false
|
|
}
|
|
}
|
|
|
|
for _, role := range d.TranslateRoles {
|
|
if len(role.Partitions) > 0 {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// Directives is a sortable slice of Directive.
|
|
type Directives []*Directive
|
|
|
|
func (d Directives) Len() int { return len(d) }
|
|
func (d Directives) Less(i, j int) bool { return d[i].Version < d[j].Version }
|
|
func (d Directives) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|