github.com/ryanslade/nomad@v0.2.4-0.20160128061903-fc95782f2089/nomad/state/schema.go (about)

     1  package state
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hashicorp/go-memdb"
     7  	"github.com/hashicorp/nomad/nomad/structs"
     8  )
     9  
    10  // stateStoreSchema is used to return the schema for the state store
    11  func stateStoreSchema() *memdb.DBSchema {
    12  	// Create the root DB schema
    13  	db := &memdb.DBSchema{
    14  		Tables: make(map[string]*memdb.TableSchema),
    15  	}
    16  
    17  	// Collect all the schemas that are needed
    18  	schemas := []func() *memdb.TableSchema{
    19  		indexTableSchema,
    20  		nodeTableSchema,
    21  		jobTableSchema,
    22  		periodicLaunchTableSchema,
    23  		evalTableSchema,
    24  		allocTableSchema,
    25  	}
    26  
    27  	// Add each of the tables
    28  	for _, schemaFn := range schemas {
    29  		schema := schemaFn()
    30  		if _, ok := db.Tables[schema.Name]; ok {
    31  			panic(fmt.Sprintf("duplicate table name: %s", schema.Name))
    32  		}
    33  		db.Tables[schema.Name] = schema
    34  	}
    35  	return db
    36  }
    37  
    38  // indexTableSchema is used for
    39  func indexTableSchema() *memdb.TableSchema {
    40  	return &memdb.TableSchema{
    41  		Name: "index",
    42  		Indexes: map[string]*memdb.IndexSchema{
    43  			"id": &memdb.IndexSchema{
    44  				Name:         "id",
    45  				AllowMissing: false,
    46  				Unique:       true,
    47  				Indexer: &memdb.StringFieldIndex{
    48  					Field:     "Key",
    49  					Lowercase: true,
    50  				},
    51  			},
    52  		},
    53  	}
    54  }
    55  
    56  // nodeTableSchema returns the MemDB schema for the nodes table.
    57  // This table is used to store all the client nodes that are registered.
    58  func nodeTableSchema() *memdb.TableSchema {
    59  	return &memdb.TableSchema{
    60  		Name: "nodes",
    61  		Indexes: map[string]*memdb.IndexSchema{
    62  			// Primary index is used for node management
    63  			// and simple direct lookup. ID is required to be
    64  			// unique.
    65  			"id": &memdb.IndexSchema{
    66  				Name:         "id",
    67  				AllowMissing: false,
    68  				Unique:       true,
    69  				Indexer: &memdb.UUIDFieldIndex{
    70  					Field: "ID",
    71  				},
    72  			},
    73  		},
    74  	}
    75  }
    76  
    77  // jobTableSchema returns the MemDB schema for the jobs table.
    78  // This table is used to store all the jobs that have been submitted.
    79  func jobTableSchema() *memdb.TableSchema {
    80  	return &memdb.TableSchema{
    81  		Name: "jobs",
    82  		Indexes: map[string]*memdb.IndexSchema{
    83  			// Primary index is used for job management
    84  			// and simple direct lookup. ID is required to be
    85  			// unique.
    86  			"id": &memdb.IndexSchema{
    87  				Name:         "id",
    88  				AllowMissing: false,
    89  				Unique:       true,
    90  				Indexer: &memdb.StringFieldIndex{
    91  					Field:     "ID",
    92  					Lowercase: true,
    93  				},
    94  			},
    95  			"type": &memdb.IndexSchema{
    96  				Name:         "type",
    97  				AllowMissing: false,
    98  				Unique:       false,
    99  				Indexer: &memdb.StringFieldIndex{
   100  					Field:     "Type",
   101  					Lowercase: false,
   102  				},
   103  			},
   104  			"gc": &memdb.IndexSchema{
   105  				Name:         "gc",
   106  				AllowMissing: false,
   107  				Unique:       false,
   108  				Indexer: &memdb.ConditionalIndex{
   109  					Conditional: jobIsGCable,
   110  				},
   111  			},
   112  			"periodic": &memdb.IndexSchema{
   113  				Name:         "periodic",
   114  				AllowMissing: false,
   115  				Unique:       false,
   116  				Indexer: &memdb.ConditionalIndex{
   117  					Conditional: jobIsPeriodic,
   118  				},
   119  			},
   120  		},
   121  	}
   122  }
   123  
   124  // jobIsGCable satisfies the ConditionalIndexFunc interface and creates an index
   125  // on whether a job is eligible for garbage collection.
   126  func jobIsGCable(obj interface{}) (bool, error) {
   127  	j, ok := obj.(*structs.Job)
   128  	if !ok {
   129  		return false, fmt.Errorf("Unexpected type: %v", obj)
   130  	}
   131  
   132  	return j.GC, nil
   133  }
   134  
   135  // jobIsPeriodic satisfies the ConditionalIndexFunc interface and creates an index
   136  // on whether a job is periodic.
   137  func jobIsPeriodic(obj interface{}) (bool, error) {
   138  	j, ok := obj.(*structs.Job)
   139  	if !ok {
   140  		return false, fmt.Errorf("Unexpected type: %v", obj)
   141  	}
   142  
   143  	if j.Periodic != nil && j.Periodic.Enabled == true {
   144  		return true, nil
   145  	}
   146  
   147  	return false, nil
   148  }
   149  
   150  // periodicLaunchTableSchema returns the MemDB schema tracking the most recent
   151  // launch time for a perioidic job.
   152  func periodicLaunchTableSchema() *memdb.TableSchema {
   153  	return &memdb.TableSchema{
   154  		Name: "periodic_launch",
   155  		Indexes: map[string]*memdb.IndexSchema{
   156  			// Primary index is used for job management
   157  			// and simple direct lookup. ID is required to be
   158  			// unique.
   159  			"id": &memdb.IndexSchema{
   160  				Name:         "id",
   161  				AllowMissing: false,
   162  				Unique:       true,
   163  				Indexer: &memdb.StringFieldIndex{
   164  					Field:     "ID",
   165  					Lowercase: true,
   166  				},
   167  			},
   168  		},
   169  	}
   170  }
   171  
   172  // evalTableSchema returns the MemDB schema for the eval table.
   173  // This table is used to store all the evaluations that are pending
   174  // or recently completed.
   175  func evalTableSchema() *memdb.TableSchema {
   176  	return &memdb.TableSchema{
   177  		Name: "evals",
   178  		Indexes: map[string]*memdb.IndexSchema{
   179  			// Primary index is used for direct lookup.
   180  			"id": &memdb.IndexSchema{
   181  				Name:         "id",
   182  				AllowMissing: false,
   183  				Unique:       true,
   184  				Indexer: &memdb.UUIDFieldIndex{
   185  					Field: "ID",
   186  				},
   187  			},
   188  
   189  			// Job index is used to lookup allocations by job
   190  			"job": &memdb.IndexSchema{
   191  				Name:         "job",
   192  				AllowMissing: false,
   193  				Unique:       false,
   194  				Indexer: &memdb.StringFieldIndex{
   195  					Field:     "JobID",
   196  					Lowercase: true,
   197  				},
   198  			},
   199  		},
   200  	}
   201  }
   202  
   203  // allocTableSchema returns the MemDB schema for the allocation table.
   204  // This table is used to store all the task allocations between task groups
   205  // and nodes.
   206  func allocTableSchema() *memdb.TableSchema {
   207  	return &memdb.TableSchema{
   208  		Name: "allocs",
   209  		Indexes: map[string]*memdb.IndexSchema{
   210  			// Primary index is a UUID
   211  			"id": &memdb.IndexSchema{
   212  				Name:         "id",
   213  				AllowMissing: false,
   214  				Unique:       true,
   215  				Indexer: &memdb.UUIDFieldIndex{
   216  					Field: "ID",
   217  				},
   218  			},
   219  
   220  			// Node index is used to lookup allocations by node
   221  			"node": &memdb.IndexSchema{
   222  				Name:         "node",
   223  				AllowMissing: true, // Missing is allow for failed allocations
   224  				Unique:       false,
   225  				Indexer: &memdb.StringFieldIndex{
   226  					Field:     "NodeID",
   227  					Lowercase: true,
   228  				},
   229  			},
   230  
   231  			// Job index is used to lookup allocations by job
   232  			"job": &memdb.IndexSchema{
   233  				Name:         "job",
   234  				AllowMissing: false,
   235  				Unique:       false,
   236  				Indexer: &memdb.StringFieldIndex{
   237  					Field:     "JobID",
   238  					Lowercase: true,
   239  				},
   240  			},
   241  
   242  			// Eval index is used to lookup allocations by eval
   243  			"eval": &memdb.IndexSchema{
   244  				Name:         "eval",
   245  				AllowMissing: false,
   246  				Unique:       false,
   247  				Indexer: &memdb.UUIDFieldIndex{
   248  					Field: "EvalID",
   249  				},
   250  			},
   251  		},
   252  	}
   253  }