2015-08-11 21:27:14 +00:00
|
|
|
package state
|
2015-07-03 21:46:30 +00:00
|
|
|
|
2015-07-03 23:57:48 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-memdb"
|
2015-12-15 03:20:57 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
2015-07-03 23:57:48 +00:00
|
|
|
)
|
2015-07-03 21:46:30 +00:00
|
|
|
|
|
|
|
// stateStoreSchema is used to return the schema for the state store
|
|
|
|
func stateStoreSchema() *memdb.DBSchema {
|
2015-07-03 23:04:24 +00:00
|
|
|
// Create the root DB schema
|
|
|
|
db := &memdb.DBSchema{
|
|
|
|
Tables: make(map[string]*memdb.TableSchema),
|
|
|
|
}
|
|
|
|
|
2015-07-03 23:57:48 +00:00
|
|
|
// Collect all the schemas that are needed
|
|
|
|
schemas := []func() *memdb.TableSchema{
|
2015-07-06 21:30:43 +00:00
|
|
|
indexTableSchema,
|
2015-07-03 23:57:48 +00:00
|
|
|
nodeTableSchema,
|
|
|
|
jobTableSchema,
|
2015-07-23 22:27:13 +00:00
|
|
|
evalTableSchema,
|
2015-07-04 00:11:53 +00:00
|
|
|
allocTableSchema,
|
2015-07-03 23:57:48 +00:00
|
|
|
}
|
2015-07-03 23:04:24 +00:00
|
|
|
|
2015-07-03 23:57:48 +00:00
|
|
|
// Add each of the tables
|
|
|
|
for _, schemaFn := range schemas {
|
|
|
|
schema := schemaFn()
|
|
|
|
if _, ok := db.Tables[schema.Name]; ok {
|
|
|
|
panic(fmt.Sprintf("duplicate table name: %s", schema.Name))
|
|
|
|
}
|
|
|
|
db.Tables[schema.Name] = schema
|
|
|
|
}
|
2015-07-03 23:04:24 +00:00
|
|
|
return db
|
|
|
|
}
|
|
|
|
|
2015-07-06 21:30:43 +00:00
|
|
|
// indexTableSchema is used for
|
|
|
|
func indexTableSchema() *memdb.TableSchema {
|
|
|
|
return &memdb.TableSchema{
|
|
|
|
Name: "index",
|
|
|
|
Indexes: map[string]*memdb.IndexSchema{
|
|
|
|
"id": &memdb.IndexSchema{
|
|
|
|
Name: "id",
|
|
|
|
AllowMissing: false,
|
|
|
|
Unique: true,
|
|
|
|
Indexer: &memdb.StringFieldIndex{
|
|
|
|
Field: "Key",
|
|
|
|
Lowercase: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-03 23:04:24 +00:00
|
|
|
// nodeTableSchema returns the MemDB schema for the nodes table.
|
|
|
|
// This table is used to store all the client nodes that are registered.
|
|
|
|
func nodeTableSchema() *memdb.TableSchema {
|
2015-07-03 23:57:48 +00:00
|
|
|
return &memdb.TableSchema{
|
2015-07-03 23:04:24 +00:00
|
|
|
Name: "nodes",
|
|
|
|
Indexes: map[string]*memdb.IndexSchema{
|
|
|
|
// Primary index is used for node management
|
|
|
|
// and simple direct lookup. ID is required to be
|
|
|
|
// unique.
|
|
|
|
"id": &memdb.IndexSchema{
|
|
|
|
Name: "id",
|
|
|
|
AllowMissing: false,
|
|
|
|
Unique: true,
|
|
|
|
Indexer: &memdb.StringFieldIndex{
|
|
|
|
Field: "ID",
|
|
|
|
Lowercase: true,
|
|
|
|
},
|
|
|
|
},
|
2015-07-03 23:57:48 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// jobTableSchema returns the MemDB schema for the jobs table.
|
|
|
|
// This table is used to store all the jobs that have been submitted.
|
|
|
|
func jobTableSchema() *memdb.TableSchema {
|
|
|
|
return &memdb.TableSchema{
|
|
|
|
Name: "jobs",
|
|
|
|
Indexes: map[string]*memdb.IndexSchema{
|
|
|
|
// Primary index is used for job management
|
|
|
|
// and simple direct lookup. ID is required to be
|
|
|
|
// unique.
|
|
|
|
"id": &memdb.IndexSchema{
|
|
|
|
Name: "id",
|
|
|
|
AllowMissing: false,
|
|
|
|
Unique: true,
|
|
|
|
Indexer: &memdb.StringFieldIndex{
|
2015-07-23 22:15:48 +00:00
|
|
|
Field: "ID",
|
2015-07-03 23:57:48 +00:00
|
|
|
Lowercase: true,
|
|
|
|
},
|
|
|
|
},
|
2015-10-20 17:57:53 +00:00
|
|
|
"type": &memdb.IndexSchema{
|
|
|
|
Name: "type",
|
|
|
|
AllowMissing: false,
|
|
|
|
Unique: false,
|
|
|
|
Indexer: &memdb.StringFieldIndex{
|
|
|
|
Field: "Type",
|
|
|
|
Lowercase: false,
|
|
|
|
},
|
|
|
|
},
|
2015-12-15 03:20:57 +00:00
|
|
|
"gc": &memdb.IndexSchema{
|
|
|
|
Name: "gc",
|
|
|
|
AllowMissing: false,
|
|
|
|
Unique: false,
|
|
|
|
Indexer: &memdb.ConditionalIndex{
|
|
|
|
Conditional: jobIsGCable,
|
|
|
|
},
|
|
|
|
},
|
2015-07-03 23:57:48 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-15 03:20:57 +00:00
|
|
|
// jobIsGCable satisfies the ConditionalIndexFunc interface and creates an index
|
|
|
|
// on whether a job is eligible for garbage collection.
|
|
|
|
func jobIsGCable(obj interface{}) (bool, error) {
|
|
|
|
j, ok := obj.(*structs.Job)
|
|
|
|
if !ok {
|
|
|
|
return false, fmt.Errorf("Unexpected type: %v", obj)
|
|
|
|
}
|
|
|
|
|
2015-12-15 21:07:25 +00:00
|
|
|
return j.GC, nil
|
2015-12-15 03:20:57 +00:00
|
|
|
}
|
|
|
|
|
2015-07-23 22:27:13 +00:00
|
|
|
// evalTableSchema returns the MemDB schema for the eval table.
|
|
|
|
// This table is used to store all the evaluations that are pending
|
|
|
|
// or recently completed.
|
|
|
|
func evalTableSchema() *memdb.TableSchema {
|
2015-07-03 23:57:48 +00:00
|
|
|
return &memdb.TableSchema{
|
2015-07-23 22:27:13 +00:00
|
|
|
Name: "evals",
|
2015-07-03 23:57:48 +00:00
|
|
|
Indexes: map[string]*memdb.IndexSchema{
|
2015-07-23 22:27:13 +00:00
|
|
|
// Primary index is used for direct lookup.
|
2015-07-03 23:57:48 +00:00
|
|
|
"id": &memdb.IndexSchema{
|
|
|
|
Name: "id",
|
|
|
|
AllowMissing: false,
|
|
|
|
Unique: true,
|
2015-07-23 22:27:13 +00:00
|
|
|
Indexer: &memdb.UUIDFieldIndex{
|
|
|
|
Field: "ID",
|
2015-07-03 23:57:48 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
2015-08-15 20:27:42 +00:00
|
|
|
// Job index is used to lookup allocations by job
|
|
|
|
"job": &memdb.IndexSchema{
|
|
|
|
Name: "job",
|
|
|
|
AllowMissing: false,
|
|
|
|
Unique: false,
|
|
|
|
Indexer: &memdb.StringFieldIndex{
|
|
|
|
Field: "JobID",
|
|
|
|
Lowercase: true,
|
|
|
|
},
|
|
|
|
},
|
2015-07-03 23:04:24 +00:00
|
|
|
},
|
|
|
|
}
|
2015-07-03 21:46:30 +00:00
|
|
|
}
|
2015-07-04 00:11:53 +00:00
|
|
|
|
|
|
|
// allocTableSchema returns the MemDB schema for the allocation table.
|
|
|
|
// This table is used to store all the task allocations between task groups
|
|
|
|
// and nodes.
|
|
|
|
func allocTableSchema() *memdb.TableSchema {
|
|
|
|
return &memdb.TableSchema{
|
|
|
|
Name: "allocs",
|
|
|
|
Indexes: map[string]*memdb.IndexSchema{
|
|
|
|
// Primary index is a UUID
|
|
|
|
"id": &memdb.IndexSchema{
|
2015-07-04 00:48:02 +00:00
|
|
|
Name: "id",
|
2015-07-04 00:11:53 +00:00
|
|
|
AllowMissing: false,
|
|
|
|
Unique: true,
|
|
|
|
Indexer: &memdb.UUIDFieldIndex{
|
|
|
|
Field: "ID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
// Node index is used to lookup allocations by node
|
|
|
|
"node": &memdb.IndexSchema{
|
|
|
|
Name: "node",
|
2015-08-15 20:27:42 +00:00
|
|
|
AllowMissing: true, // Missing is allow for failed allocations
|
2015-07-04 00:11:53 +00:00
|
|
|
Unique: false,
|
|
|
|
Indexer: &memdb.StringFieldIndex{
|
|
|
|
Field: "NodeID",
|
|
|
|
Lowercase: true,
|
|
|
|
},
|
|
|
|
},
|
2015-08-07 00:36:10 +00:00
|
|
|
|
|
|
|
// Job index is used to lookup allocations by job
|
|
|
|
"job": &memdb.IndexSchema{
|
|
|
|
Name: "job",
|
|
|
|
AllowMissing: false,
|
|
|
|
Unique: false,
|
|
|
|
Indexer: &memdb.StringFieldIndex{
|
|
|
|
Field: "JobID",
|
|
|
|
Lowercase: true,
|
|
|
|
},
|
|
|
|
},
|
2015-08-15 20:27:42 +00:00
|
|
|
|
|
|
|
// Eval index is used to lookup allocations by eval
|
|
|
|
"eval": &memdb.IndexSchema{
|
|
|
|
Name: "eval",
|
|
|
|
AllowMissing: false,
|
|
|
|
Unique: false,
|
|
|
|
Indexer: &memdb.UUIDFieldIndex{
|
|
|
|
Field: "EvalID",
|
|
|
|
},
|
|
|
|
},
|
2015-07-04 00:11:53 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|