1package gen 2 3import ( 4 "fmt" 5) 6 7type Visitor interface { 8 Visit(node SchemaNode) (w Visitor) 9} 10 11type SchemaNode interface { 12 node() 13} 14 15type Schema struct { 16 Title string 17 Version string 18 SeriesLimit *SeriesLimit `toml:"series-limit"` 19 Measurements Measurements 20} 21 22func (*Schema) node() {} 23 24type Measurements []Measurement 25 26func (Measurements) node() {} 27 28type Tags []Tag 29 30func (Tags) node() {} 31 32type Fields []Field 33 34func (Fields) node() {} 35 36type Measurement struct { 37 Name string 38 SeriesLimit *SeriesLimit `toml:"series-limit"` 39 Sample *sample 40 Tags Tags 41 Fields Fields 42} 43 44func (*Measurement) node() {} 45 46type TagSource interface { 47 fmt.Stringer 48 SchemaNode 49 tagsource() 50} 51 52type Tag struct { 53 Name string 54 Source TagSource 55} 56 57func (*Tag) node() {} 58 59type TagArraySource struct { 60 Values []string 61} 62 63func (*TagArraySource) node() {} 64func (*TagArraySource) tagsource() {} 65 66func (s *TagArraySource) String() string { 67 return fmt.Sprintf("array, source=%#v", s.Values) 68} 69 70type TagSequenceSource struct { 71 Format string 72 Start int64 73 Count int64 74} 75 76func (*TagSequenceSource) node() {} 77func (*TagSequenceSource) tagsource() {} 78 79func (t *TagSequenceSource) String() string { 80 return fmt.Sprintf("sequence, prefix=%q, range=[%d,%d)", t.Format, t.Start, t.Start+t.Count) 81} 82 83type TagFileSource struct { 84 Path string 85} 86 87func (*TagFileSource) node() {} 88func (*TagFileSource) tagsource() {} 89 90func (s *TagFileSource) String() string { 91 return fmt.Sprintf("file, path=%s", s.Path) 92} 93 94type FieldSource interface { 95 fmt.Stringer 96 SchemaNode 97 fieldsource() 98} 99 100type Field struct { 101 Name string 102 Count int64 103 TimePrecision *precision `toml:"time-precision"` // TimePrecision determines the precision for generated timestamp values 104 TimeInterval *duration `toml:"time-interval"` // TimeInterval determines the duration between timestamp values 105 Source FieldSource 106} 107 108func (t *Field) TimeSequenceSpec() TimeSequenceSpec { 109 if t.TimeInterval != nil { 110 return TimeSequenceSpec{ 111 Count: int(t.Count), 112 Delta: t.TimeInterval.Duration, 113 } 114 } 115 116 if t.TimePrecision != nil { 117 return TimeSequenceSpec{ 118 Count: int(t.Count), 119 Precision: t.TimePrecision.ToDuration(), 120 } 121 } 122 123 panic("TimeInterval and TimePrecision are nil") 124} 125 126func (*Field) node() {} 127 128type FieldConstantValue struct { 129 Value interface{} 130} 131 132func (*FieldConstantValue) node() {} 133func (*FieldConstantValue) fieldsource() {} 134 135func (f *FieldConstantValue) String() string { 136 return fmt.Sprintf("constant, source=%#v", f.Value) 137} 138 139type FieldArraySource struct { 140 Value interface{} 141} 142 143func (*FieldArraySource) node() {} 144func (*FieldArraySource) fieldsource() {} 145 146func (f *FieldArraySource) String() string { 147 return fmt.Sprintf("array, source=%#v", f.Value) 148} 149 150type FieldFloatRandomSource struct { 151 Seed int64 152 Min, Max float64 153} 154 155func (*FieldFloatRandomSource) node() {} 156func (*FieldFloatRandomSource) fieldsource() {} 157 158func (f *FieldFloatRandomSource) String() string { 159 return fmt.Sprintf("rand<float>, seed=%d, min=%f, max=%f", f.Seed, f.Max, f.Max) 160} 161 162type FieldIntegerZipfSource struct { 163 Seed int64 164 S, V float64 165 IMAX uint64 166} 167 168func (*FieldIntegerZipfSource) node() {} 169func (*FieldIntegerZipfSource) fieldsource() {} 170 171func (f *FieldIntegerZipfSource) String() string { 172 return fmt.Sprintf("rand<float>, seed=%d, s=%f, v=%f, imax=%d", f.Seed, f.S, f.V, f.IMAX) 173} 174 175type VisitorFn func(node SchemaNode) bool 176 177func (fn VisitorFn) Visit(node SchemaNode) (w Visitor) { 178 if fn(node) { 179 return fn 180 } 181 return nil 182} 183 184// WalkDown performs a pre-order, depth-first traversal of the graph, calling v for each node. 185// Pre-order starts by calling the visitor for the root and each child as it traverses down 186// the graph to the leaves. 187func WalkDown(v Visitor, node SchemaNode) { 188 walk(v, node, false) 189} 190 191// WalkUp performs a post-order, depth-first traversal of the graph, calling v for each node. 192// Post-order starts by calling the visitor for the leaves then each parent as it traverses up 193// the graph to the root. 194func WalkUp(v Visitor, node SchemaNode) { 195 walk(v, node, true) 196} 197 198func walk(v Visitor, node SchemaNode, up bool) Visitor { 199 if v == nil { 200 return nil 201 } 202 203 if !up { 204 if v = v.Visit(node); v == nil { 205 return nil 206 } 207 } 208 209 switch n := node.(type) { 210 case *Schema: 211 walk(v, n.Measurements, up) 212 213 case Measurements: 214 v := v 215 for i := range n { 216 v = walk(v, &n[i], up) 217 } 218 219 case *Measurement: 220 v := v 221 v = walk(v, n.Tags, up) 222 walk(v, n.Fields, up) 223 224 case Fields: 225 v := v 226 for i := 0; i < len(n); i++ { 227 v = walk(v, &n[i], up) 228 } 229 230 case Tags: 231 v := v 232 for i := 0; i < len(n); i++ { 233 v = walk(v, &n[i], up) 234 } 235 236 case *Tag: 237 walk(v, n.Source, up) 238 239 case *TagArraySource, *TagSequenceSource, *TagFileSource: 240 // nothing to do 241 242 case *Field: 243 walk(v, n.Source, up) 244 245 case *FieldConstantValue, *FieldArraySource, *FieldFloatRandomSource, *FieldIntegerZipfSource: 246 // nothing to do 247 248 default: 249 panic(fmt.Sprintf("schema.Walk: unexpected node type %T", n)) 250 } 251 252 if up && v != nil { 253 v = v.Visit(node) 254 } 255 256 return v 257} 258