From 7b5b3189dd45d7c4b7317b740df1b7d0f6a905b8 Mon Sep 17 00:00:00 2001 From: Mark Rushakoff Date: Fri, 30 Dec 2016 11:56:58 -0800 Subject: [PATCH] Update godoc for package models --- models/consistency.go | 14 ++-- models/inline_fnv.go | 5 ++ models/points.go | 164 ++++++++++++++++++++++++++++++++---------- models/rows.go | 3 + models/statistic.go | 2 + 5 files changed, 143 insertions(+), 45 deletions(-) diff --git a/models/consistency.go b/models/consistency.go index 97cdc51aa0..2a3269bca1 100644 --- a/models/consistency.go +++ b/models/consistency.go @@ -6,20 +6,22 @@ import ( ) // ConsistencyLevel represent a required replication criteria before a write can -// be returned as successful +// be returned as successful. +// +// The consistency level is handled in open-source InfluxDB but only applicable to clusters. type ConsistencyLevel int const ( - // ConsistencyLevelAny allows for hinted hand off, potentially no write happened yet + // ConsistencyLevelAny allows for hinted handoff, potentially no write happened yet. ConsistencyLevelAny ConsistencyLevel = iota - // ConsistencyLevelOne requires at least one data node acknowledged a write + // ConsistencyLevelOne requires at least one data node acknowledged a write. ConsistencyLevelOne - // ConsistencyLevelQuorum requires a quorum of data nodes to acknowledge a write + // ConsistencyLevelQuorum requires a quorum of data nodes to acknowledge a write. ConsistencyLevelQuorum - // ConsistencyLevelAll requires all data nodes to acknowledge a write + // ConsistencyLevelAll requires all data nodes to acknowledge a write. ConsistencyLevelAll ) @@ -29,7 +31,7 @@ var ( ErrInvalidConsistencyLevel = errors.New("invalid consistency level") ) -// ParseConsistencyLevel converts a consistency level string to the corresponding ConsistencyLevel const +// ParseConsistencyLevel converts a consistency level string to the corresponding ConsistencyLevel const. func ParseConsistencyLevel(level string) (ConsistencyLevel, error) { switch strings.ToLower(level) { case "any": diff --git a/models/inline_fnv.go b/models/inline_fnv.go index dea25901cc..eec1ae8b01 100644 --- a/models/inline_fnv.go +++ b/models/inline_fnv.go @@ -7,12 +7,15 @@ const ( ) // InlineFNV64a is an alloc-free port of the standard library's fnv64a. +// See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function. type InlineFNV64a uint64 +// NewInlineFNV64a returns a new instance of InlineFNV64a. func NewInlineFNV64a() InlineFNV64a { return offset64 } +// Write adds data to the running hash. func (s *InlineFNV64a) Write(data []byte) (int, error) { hash := uint64(*s) for _, c := range data { @@ -22,6 +25,8 @@ func (s *InlineFNV64a) Write(data []byte) (int, error) { *s = InlineFNV64a(hash) return len(data), nil } + +// Sum64 returns the uint64 of the current resulting hash. func (s *InlineFNV64a) Sum64() uint64 { return uint64(*s) } diff --git a/models/points.go b/models/points.go index e44b7a3224..0da2f7f3e4 100644 --- a/models/points.go +++ b/models/points.go @@ -1,3 +1,4 @@ +// Package models implements basic objects used throughout the TICK stack. package models // import "github.com/influxdata/influxdb/models" import ( @@ -26,53 +27,75 @@ var ( '=': []byte(`\=`), } - ErrPointMustHaveAField = errors.New("point without fields is unsupported") - ErrInvalidNumber = errors.New("invalid number") - ErrInvalidPoint = errors.New("point is invalid") - ErrMaxKeyLengthExceeded = errors.New("max key length exceeded") + // ErrPointMustHaveAField is returned when operating on a point that does not have any fields. + ErrPointMustHaveAField = errors.New("point without fields is unsupported") + + // ErrInvalidNumber is returned when a number is expected but not provided. + ErrInvalidNumber = errors.New("invalid number") + + // ErrInvalidPoint is returned when a point cannot be parsed correctly. + ErrInvalidPoint = errors.New("point is invalid") ) const ( + // MaxKeyLength is the largest allowed size of the combined measurement and tag keys. MaxKeyLength = 65535 ) -// Point defines the values that will be written to the database +// Point defines the values that will be written to the database. type Point interface { + // Name return the measurement name for the point. Name() string + + // SetName updates the measurement name for the point. SetName(string) + // Tags returns the tag set for the point. Tags() Tags + + // AddTag adds or replaces a tag value for a point. AddTag(key, value string) + + // SetTags replaces the tags for the point. SetTags(tags Tags) + // Fields returns the fields for the point. Fields() Fields + // Time return the timestamp for the point. Time() time.Time + + // SetTime updates the timestamp for the point. SetTime(t time.Time) + + // UnixNano returns the timestamp of the point as nanoseconds since Unix epoch. UnixNano() int64 + // HashID returns a non-cryptographic checksum of the point's key. HashID() uint64 + + // Key returns the key (measurement joined with tags) of the point. Key() []byte Data() []byte SetData(buf []byte) - // String returns a string representation of the point, if there is a + // String returns a string representation of the point. If there is a // timestamp associated with the point then it will be specified with the default - // precision of nanoseconds + // precision of nanoseconds. String() string - // Bytes returns a []byte representation of the point similar to string. + // MarshalBinary returns a binary representation of the point. MarshalBinary() ([]byte, error) - // PrecisionString returns a string representation of the point, if there + // PrecisionString returns a string representation of the point. If there // is a timestamp associated with the point then it will be specified in the - // given unit + // given unit. PrecisionString(precision string) string - // RoundedString returns a string representation of the point, if there + // RoundedString returns a string representation of the point. If there // is a timestamp associated with the point, then it will be rounded to the - // given duration + // given duration. RoundedString(d time.Duration) string // Split will attempt to return multiple points with the same timestamp whose @@ -80,50 +103,82 @@ type Point interface { // a point without a timestamp may exceed the requested size. Split(size int) []Point - // Round will round the timestamp of the point to the given duration + // Round will round the timestamp of the point to the given duration. Round(d time.Duration) - // StringSize returns the length of the string that would be returned by String() + // StringSize returns the length of the string that would be returned by String(). StringSize() int // AppendString appends the result of String() to the provided buffer and returns - // the result, potentially reducing string allocations + // the result, potentially reducing string allocations. AppendString(buf []byte) []byte // FieldIterator retuns a FieldIterator that can be used to traverse the - // fields of a point without constructing the in-memory map + // fields of a point without constructing the in-memory map. FieldIterator() FieldIterator } +// FieldType represents the type of a field. type FieldType int const ( + // Integer indicates the field's type is integer. Integer FieldType = iota + + // Float indicates the field's type is float. Float + + // Boolean indicates the field's type is boolean. Boolean + + // String indicates the field's type is string. String + + // Empty is used to indicate that there is no field. Empty ) +// FieldIterator provides a low-allocation interface to iterate through a point's fields. type FieldIterator interface { + // Next indicates whether there any fields remaining. Next() bool + + // FieldKey returns the key of the current field. FieldKey() []byte + + // Type returns the FieldType of the current field. Type() FieldType + + // StringValue returns the string value of the current field. StringValue() string + + // IntegerValue returns the integer value of the current field. IntegerValue() int64 + + // BooleanValue returns the boolean value of the current field. BooleanValue() bool + + // FloatValue returns the float value of the current field. FloatValue() float64 + // Delete deletes the current field. Delete() + + // Reset resets the iterator to its initial state. Reset() } // Points represents a sortable list of points by timestamp. type Points []Point -func (a Points) Len() int { return len(a) } +// Len implements sort.Interface. +func (a Points) Len() int { return len(a) } + +// Less implements sort.Interface. func (a Points) Less(i, j int) bool { return a[i].Time().Before(a[j].Time()) } -func (a Points) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// Swap implements sort.Interface. +func (a Points) Swap(i, j int) { a[i], a[j] = a[j], a[i] } // point is the default implementation of Point. type point struct { @@ -178,8 +233,7 @@ func ParsePoints(buf []byte) ([]Point, error) { return ParsePointsWithPrecision(buf, time.Now().UTC(), "n") } -// ParsePointsString is identical to ParsePoints but accepts a string -// buffer. +// ParsePointsString is identical to ParsePoints but accepts a string. func ParsePointsString(buf string) ([]Point, error) { return ParsePoints([]byte(buf)) } @@ -312,7 +366,7 @@ func parsePoint(buf []byte, defaultTime time.Time, precision string) (Point, err return pt, nil } -// GetPrecisionMultiplier will return a multiplier for the precision specified +// GetPrecisionMultiplier will return a multiplier for the precision specified. func GetPrecisionMultiplier(precision string) int64 { d := time.Nanosecond switch precision { @@ -591,7 +645,7 @@ func less(buf []byte, indices []int, i, j int) bool { } // scanFields scans buf, starting at i for the fields section of a point. It returns -// the ending position and the byte slice of the fields within buf +// the ending position and the byte slice of the fields within buf. func scanFields(buf []byte, i int) (int, []byte, error) { start := skipWhitespace(buf, i) i = start @@ -904,7 +958,7 @@ func scanBoolean(buf []byte, i int) (int, []byte, error) { } // skipWhitespace returns the end position within buf, starting at i after -// scanning over spaces in tags +// scanning over spaces in tags. func skipWhitespace(buf []byte, i int) int { for i < len(buf) { if buf[i] != ' ' && buf[i] != '\t' && buf[i] != 0 { @@ -1106,13 +1160,13 @@ func unescapeTag(in []byte) []byte { var escapeStringFieldReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`) // EscapeStringField returns a copy of in with any double quotes or -// backslashes with escaped values +// backslashes with escaped values. func EscapeStringField(in string) string { return escapeStringFieldReplacer.Replace(in) } // unescapeStringField returns a copy of in with any escaped double-quotes -// or backslashes unescaped +// or backslashes unescaped. func unescapeStringField(in string) string { if strings.IndexByte(in, '\\') == -1 { return in @@ -1159,7 +1213,7 @@ func NewPoint(name string, tags Tags, fields Fields, t time.Time) (Point, error) } // pointKey checks some basic requirements for valid points, and returns the -// key, along with an possible error +// key, along with an possible error. func pointKey(measurement string, tags Tags, fields Fields, t time.Time) ([]byte, error) { if len(fields) == 0 { return nil, ErrPointMustHaveAField @@ -1227,6 +1281,7 @@ func (p *point) SetData(b []byte) { p.data = b } +// Key returns the key (measurement joined with tags) of the point. func (p *point) Key() []byte { return p.key } @@ -1236,7 +1291,7 @@ func (p *point) name() []byte { return name } -// Name return the measurement name for the point +// Name return the measurement name for the point. func (p *point) Name() string { if p.cachedName != "" { return p.cachedName @@ -1245,28 +1300,28 @@ func (p *point) Name() string { return p.cachedName } -// SetName updates the measurement name for the point +// SetName updates the measurement name for the point. func (p *point) SetName(name string) { p.cachedName = "" p.key = MakeKey([]byte(name), p.Tags()) } -// Time return the timestamp for the point +// Time return the timestamp for the point. func (p *point) Time() time.Time { return p.time } -// SetTime updates the timestamp for the point +// SetTime updates the timestamp for the point. func (p *point) SetTime(t time.Time) { p.time = t } -// Round implements Point.Round +// Round will round the timestamp of the point to the given duration. func (p *point) Round(d time.Duration) { p.time = p.time.Round(d) } -// Tags returns the tag set for the point +// Tags returns the tag set for the point. func (p *point) Tags() Tags { if p.cachedTags != nil { return p.cachedTags @@ -1322,13 +1377,13 @@ func MakeKey(name []byte, tags Tags) []byte { return append(escapeMeasurement(unescapeMeasurement(name)), tags.HashKey()...) } -// SetTags replaces the tags for the point +// SetTags replaces the tags for the point. func (p *point) SetTags(tags Tags) { p.key = MakeKey([]byte(p.Name()), tags) p.cachedTags = tags } -// AddTag adds or replaces a tag value for a point +// AddTag adds or replaces a tag value for a point. func (p *point) AddTag(key, value string) { tags := p.Tags() tags = append(tags, Tag{Key: []byte(key), Value: []byte(value)}) @@ -1337,7 +1392,7 @@ func (p *point) AddTag(key, value string) { p.key = MakeKey([]byte(p.Name()), tags) } -// Fields returns the fields for the point +// Fields returns the fields for the point. func (p *point) Fields() Fields { if p.cachedFields != nil { return p.cachedFields @@ -1346,7 +1401,7 @@ func (p *point) Fields() Fields { return p.cachedFields } -// SetPrecision will round a time to the specified precision +// SetPrecision will round a time to the specified precision. func (p *point) SetPrecision(precision string) { switch precision { case "n": @@ -1363,6 +1418,7 @@ func (p *point) SetPrecision(precision string) { } } +// String returns the string representation of the point. func (p *point) String() string { if p.Time().IsZero() { return string(p.Key()) + " " + string(p.fields) @@ -1370,7 +1426,7 @@ func (p *point) String() string { return string(p.Key()) + " " + string(p.fields) + " " + strconv.FormatInt(p.UnixNano(), 10) } -// AppendString implements Point.AppendString +// AppendString appends the string representation of the point to buf. func (p *point) AppendString(buf []byte) []byte { buf = append(buf, p.key...) buf = append(buf, ' ') @@ -1384,6 +1440,7 @@ func (p *point) AppendString(buf []byte) []byte { return buf } +// StringSize returns the length of the string that would be returned by String(). func (p *point) StringSize() int { size := len(p.key) + len(p.fields) + 1 @@ -1405,6 +1462,7 @@ func (p *point) StringSize() int { return size } +// MarshalBinary returns a binary representation of the point. func (p *point) MarshalBinary() ([]byte, error) { if len(p.fields) == 0 { return nil, ErrPointMustHaveAField @@ -1432,6 +1490,7 @@ func (p *point) MarshalBinary() ([]byte, error) { return b, nil } +// UnmarshalBinary decodes a binary representation of the point into a point struct. func (p *point) UnmarshalBinary(b []byte) error { var i int keyLen := int(binary.BigEndian.Uint32(b[:4])) @@ -1451,6 +1510,9 @@ func (p *point) UnmarshalBinary(b []byte) error { return nil } +// PrecisionString returns a string representation of the point. If there +// is a timestamp associated with the point then it will be specified in the +// given unit. func (p *point) PrecisionString(precision string) string { if p.Time().IsZero() { return fmt.Sprintf("%s %s", p.Key(), string(p.fields)) @@ -1459,6 +1521,9 @@ func (p *point) PrecisionString(precision string) string { p.UnixNano()/GetPrecisionMultiplier(precision)) } +// RoundedString returns a string representation of the point. If there +// is a timestamp associated with the point, then it will be rounded to the +// given duration. func (p *point) RoundedString(d time.Duration) string { if p.Time().IsZero() { return fmt.Sprintf("%s %s", p.Key(), string(p.fields)) @@ -1488,6 +1553,7 @@ func (p *point) unmarshalBinary() Fields { return fields } +// HashID returns a non-cryptographic checksum of the point's key. func (p *point) HashID() uint64 { h := NewInlineFNV64a() h.Write(p.key) @@ -1495,10 +1561,14 @@ func (p *point) HashID() uint64 { return sum } +// UnixNano returns the timestamp of the point as nanoseconds since Unix epoch. func (p *point) UnixNano() int64 { return p.Time().UnixNano() } +// Split will attempt to return multiple points with the same timestamp whose +// string representations are no longer than size. Points with a single field or +// a point without a timestamp may exceed the requested size. func (p *point) Split(size int) []Point { if p.time.IsZero() || len(p.String()) <= size { return []Point{p} @@ -1557,9 +1627,14 @@ func NewTags(m map[string]string) Tags { return a } -func (a Tags) Len() int { return len(a) } +// Len implements sort.Interface. +func (a Tags) Len() int { return len(a) } + +// Less implements sort.Interface. func (a Tags) Less(i, j int) bool { return bytes.Compare(a[i].Key, a[j].Key) == -1 } -func (a Tags) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// Swap implements sort.Interface. +func (a Tags) Swap(i, j int) { a[i], a[j] = a[j], a[i] } // Get returns the value for a key. func (a Tags) Get(key []byte) []byte { @@ -1696,6 +1771,8 @@ func parseNumber(val []byte) (interface{}, error) { return parseFloatBytes(val, 64) } +// FieldIterator retuns a FieldIterator that can be used to traverse the +// fields of a point without constructing the in-memory map. func (p *point) FieldIterator() FieldIterator { p.Reset() return p @@ -1708,6 +1785,7 @@ type fieldIterator struct { fieldType FieldType } +// Next indicates whether there any fields remaining. func (p *point) Next() bool { p.it.start = p.it.end if p.it.start >= len(p.fields) { @@ -1750,18 +1828,22 @@ func (p *point) Next() bool { return true } +// FieldKey returns the key of the current field. func (p *point) FieldKey() []byte { return p.it.key } +// Type returns the FieldType of the current field. func (p *point) Type() FieldType { return p.it.fieldType } +// StringValue returns the string value of the current field. func (p *point) StringValue() string { return unescapeStringField(string(p.it.valueBuf[1 : len(p.it.valueBuf)-1])) } +// IntegerValue returns the integer value of the current field. func (p *point) IntegerValue() int64 { n, err := parseIntBytes(p.it.valueBuf, 10, 64) if err != nil { @@ -1770,6 +1852,7 @@ func (p *point) IntegerValue() int64 { return n } +// BooleanValue returns the boolean value of the current field. func (p *point) BooleanValue() bool { b, err := parseBoolBytes(p.it.valueBuf) if err != nil { @@ -1778,6 +1861,7 @@ func (p *point) BooleanValue() bool { return b } +// FloatValue returns the float value of the current field. func (p *point) FloatValue() float64 { f, err := parseFloatBytes(p.it.valueBuf, 64) if err != nil { @@ -1787,6 +1871,7 @@ func (p *point) FloatValue() float64 { return f } +// Delete deletes the current field. func (p *point) Delete() { switch { case p.it.end == p.it.start: @@ -1804,6 +1889,7 @@ func (p *point) Delete() { p.it.fieldType = Empty } +// Reset resets the iterator to its initial state. func (p *point) Reset() { p.it.fieldType = Empty p.it.key = nil diff --git a/models/rows.go b/models/rows.go index 6006cdd19d..c087a4882d 100644 --- a/models/rows.go +++ b/models/rows.go @@ -42,8 +42,10 @@ func (r *Row) tagsKeys() []string { // Rows represents a collection of rows. Rows implements sort.Interface. type Rows []*Row +// Len implements sort.Interface. func (p Rows) Len() int { return len(p) } +// Less implements sort.Interface. func (p Rows) Less(i, j int) bool { // Sort by name first. if p[i].Name != p[j].Name { @@ -56,4 +58,5 @@ func (p Rows) Less(i, j int) bool { return p[i].tagsHash() < p[j].tagsHash() } +// Swap implements sort.Interface. func (p Rows) Swap(i, j int) { p[i], p[j] = p[j], p[i] } diff --git a/models/statistic.go b/models/statistic.go index 33f8089948..553e9d09fb 100644 --- a/models/statistic.go +++ b/models/statistic.go @@ -1,11 +1,13 @@ package models +// Statistic is the representation of a statistic used by the monitoring service. type Statistic struct { Name string `json:"name"` Tags map[string]string `json:"tags"` Values map[string]interface{} `json:"values"` } +// NewStatistic returns an initialized Statistic. func NewStatistic(name string) Statistic { return Statistic{ Name: name,