2014-10-22 05:32:19 +00:00
|
|
|
package influxdb
|
2014-11-01 01:31:19 +00:00
|
|
|
|
|
|
|
import (
|
2014-12-23 06:18:05 +00:00
|
|
|
"encoding/json"
|
2014-11-17 22:54:35 +00:00
|
|
|
"errors"
|
2014-12-23 06:18:05 +00:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2015-03-06 18:20:30 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/influxdb/influxdb/client"
|
2014-11-01 01:31:19 +00:00
|
|
|
)
|
|
|
|
|
2015-03-26 04:49:03 +00:00
|
|
|
var startTime time.Time
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
startTime = time.Now().UTC()
|
|
|
|
}
|
|
|
|
|
2014-11-17 22:54:35 +00:00
|
|
|
var (
|
|
|
|
// ErrServerOpen is returned when opening an already open server.
|
|
|
|
ErrServerOpen = errors.New("server already open")
|
|
|
|
|
|
|
|
// ErrServerClosed is returned when closing an already closed server.
|
|
|
|
ErrServerClosed = errors.New("server already closed")
|
|
|
|
|
|
|
|
// ErrPathRequired is returned when opening a server without a path.
|
|
|
|
ErrPathRequired = errors.New("path required")
|
|
|
|
|
2015-01-07 00:21:32 +00:00
|
|
|
// ErrUnableToJoin is returned when a server cannot join a cluster.
|
|
|
|
ErrUnableToJoin = errors.New("unable to join")
|
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
// ErrDataNodeURLRequired is returned when creating a data node without a URL.
|
|
|
|
ErrDataNodeURLRequired = errors.New("data node url required")
|
2014-12-29 23:12:51 +00:00
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
// ErrDataNodeExists is returned when creating a duplicate data node.
|
|
|
|
ErrDataNodeExists = errors.New("data node exists")
|
2014-12-29 23:12:51 +00:00
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
// ErrDataNodeNotFound is returned when dropping a non-existent data node.
|
|
|
|
ErrDataNodeNotFound = errors.New("data node not found")
|
2014-12-29 23:12:51 +00:00
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
// ErrDataNodeRequired is returned when using a blank data node id.
|
|
|
|
ErrDataNodeRequired = errors.New("data node required")
|
2014-12-29 23:12:51 +00:00
|
|
|
|
2014-11-21 14:27:59 +00:00
|
|
|
// ErrDatabaseNameRequired is returned when creating a database without a name.
|
|
|
|
ErrDatabaseNameRequired = errors.New("database name required")
|
|
|
|
|
2014-11-17 22:54:35 +00:00
|
|
|
// ErrDatabaseExists is returned when creating a duplicate database.
|
|
|
|
ErrDatabaseExists = errors.New("database exists")
|
|
|
|
|
|
|
|
// ErrDatabaseNotFound is returned when dropping a non-existent database.
|
|
|
|
ErrDatabaseNotFound = errors.New("database not found")
|
|
|
|
|
|
|
|
// ErrDatabaseRequired is returned when using a blank database name.
|
|
|
|
ErrDatabaseRequired = errors.New("database required")
|
|
|
|
|
|
|
|
// ErrClusterAdminExists is returned when creating a duplicate admin.
|
|
|
|
ErrClusterAdminExists = errors.New("cluster admin exists")
|
|
|
|
|
|
|
|
// ErrClusterAdminNotFound is returned when deleting a non-existent admin.
|
|
|
|
ErrClusterAdminNotFound = errors.New("cluster admin not found")
|
|
|
|
|
|
|
|
// ErrUserExists is returned when creating a duplicate user.
|
|
|
|
ErrUserExists = errors.New("user exists")
|
|
|
|
|
|
|
|
// ErrUserNotFound is returned when deleting a non-existent user.
|
|
|
|
ErrUserNotFound = errors.New("user not found")
|
|
|
|
|
|
|
|
// ErrUsernameRequired is returned when using a blank username.
|
|
|
|
ErrUsernameRequired = errors.New("username required")
|
|
|
|
|
|
|
|
// ErrInvalidUsername is returned when using a username with invalid characters.
|
|
|
|
ErrInvalidUsername = errors.New("invalid username")
|
|
|
|
|
2014-11-18 22:57:10 +00:00
|
|
|
// ErrRetentionPolicyExists is returned when creating a duplicate shard space.
|
2014-11-19 00:03:21 +00:00
|
|
|
ErrRetentionPolicyExists = errors.New("retention policy exists")
|
2014-11-17 22:54:35 +00:00
|
|
|
|
2014-11-18 22:57:10 +00:00
|
|
|
// ErrRetentionPolicyNotFound is returned when deleting a non-existent shard space.
|
2014-11-19 00:03:21 +00:00
|
|
|
ErrRetentionPolicyNotFound = errors.New("retention policy not found")
|
2014-11-17 22:54:35 +00:00
|
|
|
|
2014-11-18 22:57:10 +00:00
|
|
|
// ErrRetentionPolicyNameRequired is returned using a blank shard space name.
|
2014-11-19 00:03:21 +00:00
|
|
|
ErrRetentionPolicyNameRequired = errors.New("retention policy name required")
|
2014-11-17 22:54:35 +00:00
|
|
|
|
2015-03-10 18:38:31 +00:00
|
|
|
// ErrRetentionPolicyMinDuration is returned when creating replication policy with a duration smaller than RetenionPolicyMinDuration.
|
2015-03-10 16:49:54 +00:00
|
|
|
ErrRetentionPolicyMinDuration = fmt.Errorf("retention policy duration needs to be at least %s", retentionPolicyMinDuration)
|
|
|
|
|
2015-01-14 23:44:09 +00:00
|
|
|
// ErrDefaultRetentionPolicyNotFound is returned when using the default
|
|
|
|
// policy on a database but the default has not been set.
|
|
|
|
ErrDefaultRetentionPolicyNotFound = errors.New("default retention policy not found")
|
|
|
|
|
2014-11-17 22:54:35 +00:00
|
|
|
// ErrShardNotFound is returned writing to a non-existent shard.
|
|
|
|
ErrShardNotFound = errors.New("shard not found")
|
|
|
|
|
2015-02-19 23:21:51 +00:00
|
|
|
// ErrInvalidPointBuffer is returned when a buffer containing data for writing is invalid
|
|
|
|
ErrInvalidPointBuffer = errors.New("invalid point buffer")
|
|
|
|
|
2014-11-17 22:54:35 +00:00
|
|
|
// ErrReadAccessDenied is returned when a user attempts to read
|
|
|
|
// data that he or she does not have permission to read.
|
|
|
|
ErrReadAccessDenied = errors.New("read access denied")
|
|
|
|
|
2014-11-26 14:36:43 +00:00
|
|
|
// ErrReadWritePermissionsRequired is returned when required read/write permissions aren't provided.
|
|
|
|
ErrReadWritePermissionsRequired = errors.New("read/write permissions required")
|
|
|
|
|
2014-11-17 22:54:35 +00:00
|
|
|
// ErrInvalidQuery is returned when executing an unknown query type.
|
|
|
|
ErrInvalidQuery = errors.New("invalid query")
|
2014-11-24 00:15:41 +00:00
|
|
|
|
2015-02-04 00:40:50 +00:00
|
|
|
// ErrMeasurementNameRequired is returned when a point does not contain a name.
|
|
|
|
ErrMeasurementNameRequired = errors.New("measurement name required")
|
|
|
|
|
2015-01-10 20:22:57 +00:00
|
|
|
// ErrMeasurementNotFound is returned when a measurement does not exist.
|
|
|
|
ErrMeasurementNotFound = errors.New("measurement not found")
|
|
|
|
|
2015-02-23 22:37:10 +00:00
|
|
|
// ErrFieldsRequired is returned when a point does not any fields.
|
|
|
|
ErrFieldsRequired = errors.New("fields required")
|
2015-02-04 00:40:50 +00:00
|
|
|
|
2015-01-10 20:22:57 +00:00
|
|
|
// ErrFieldOverflow is returned when too many fields are created on a measurement.
|
|
|
|
ErrFieldOverflow = errors.New("field overflow")
|
|
|
|
|
2015-02-13 22:24:24 +00:00
|
|
|
// ErrFieldTypeConflict is returned when a new field already exists with a different type.
|
2015-02-13 23:10:46 +00:00
|
|
|
ErrFieldTypeConflict = errors.New("field type conflict")
|
2015-02-13 22:24:24 +00:00
|
|
|
|
2015-02-16 20:30:58 +00:00
|
|
|
// ErrFieldNotFound is returned when a field cannot be found.
|
2015-02-17 00:22:42 +00:00
|
|
|
ErrFieldNotFound = errors.New("field not found")
|
|
|
|
|
2014-11-24 00:15:41 +00:00
|
|
|
// ErrSeriesNotFound is returned when looking up a non-existent series by database, name and tags
|
2014-12-03 15:36:04 +00:00
|
|
|
ErrSeriesNotFound = errors.New("series not found")
|
2014-11-24 00:15:41 +00:00
|
|
|
|
|
|
|
// ErrSeriesExists is returned when attempting to set the id of a series by database, name and tags that already exists
|
2014-12-03 15:36:04 +00:00
|
|
|
ErrSeriesExists = errors.New("series already exists")
|
2015-01-13 17:16:43 +00:00
|
|
|
|
|
|
|
// ErrNotExecuted is returned when a statement is not executed in a query.
|
2015-01-15 19:03:31 +00:00
|
|
|
// This can occur when a previous statement in the same query has errored.
|
2015-01-13 17:16:43 +00:00
|
|
|
ErrNotExecuted = errors.New("not executed")
|
2015-01-30 15:43:29 +00:00
|
|
|
|
|
|
|
// ErrInvalidGrantRevoke is returned when a statement requests an invalid
|
|
|
|
// privilege for a user on the cluster or a database.
|
|
|
|
ErrInvalidGrantRevoke = errors.New("invalid privilege requested")
|
2015-01-20 02:44:47 +00:00
|
|
|
|
|
|
|
// ErrContinuousQueryExists is returned when creating a duplicate continuous query.
|
|
|
|
ErrContinuousQueryExists = errors.New("continuous query already exists")
|
2015-03-25 00:11:26 +00:00
|
|
|
|
|
|
|
// ErrContinuousQueryNotFound is returned when dropping a nonexistent continuous query.
|
|
|
|
ErrContinuousQueryNotFound = errors.New("continuous query not found")
|
2014-11-17 22:54:35 +00:00
|
|
|
)
|
2014-12-23 06:18:05 +00:00
|
|
|
|
2015-01-21 04:45:18 +00:00
|
|
|
// ErrAuthorize represents an authorization error.
|
|
|
|
type ErrAuthorize struct {
|
|
|
|
text string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Error returns the text of the error.
|
2015-02-05 21:04:28 +00:00
|
|
|
func (e ErrAuthorize) Error() string {
|
2015-01-21 04:45:18 +00:00
|
|
|
return e.text
|
|
|
|
}
|
|
|
|
|
|
|
|
// authorize satisfies isAuthorizationError
|
2015-02-01 18:47:48 +00:00
|
|
|
func (ErrAuthorize) authorize() {}
|
2015-01-21 04:45:18 +00:00
|
|
|
|
|
|
|
func isAuthorizationError(err error) bool {
|
|
|
|
type authorize interface {
|
|
|
|
authorize()
|
|
|
|
}
|
|
|
|
_, ok := err.(authorize)
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
// mustMarshal encodes a value to JSON.
|
|
|
|
// This will panic if an error occurs. This should only be used internally when
|
|
|
|
// an invalid marshal will cause corruption and a panic is appropriate.
|
|
|
|
func mustMarshalJSON(v interface{}) []byte {
|
|
|
|
b, err := json.Marshal(v)
|
|
|
|
if err != nil {
|
|
|
|
panic("marshal: " + err.Error())
|
|
|
|
}
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// mustUnmarshalJSON decodes a value from JSON.
|
|
|
|
// This will panic if an error occurs. This should only be used internally when
|
|
|
|
// an invalid unmarshal will cause corruption and a panic is appropriate.
|
|
|
|
func mustUnmarshalJSON(b []byte, v interface{}) {
|
|
|
|
if err := json.Unmarshal(b, v); err != nil {
|
|
|
|
panic("unmarshal: " + err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// assert will panic with a given formatted message if the given condition is false.
|
|
|
|
func assert(condition bool, msg string, v ...interface{}) {
|
|
|
|
if !condition {
|
|
|
|
panic(fmt.Sprintf("assert failed: "+msg, v...))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) }
|
|
|
|
func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) }
|
2015-03-06 18:20:30 +00:00
|
|
|
|
|
|
|
// NormalizeBatchPoints returns a slice of Points, created by populating individual
|
|
|
|
// points within the batch, which do not have timestamps or tags, with the top-level
|
|
|
|
// values.
|
|
|
|
func NormalizeBatchPoints(bp client.BatchPoints) ([]Point, error) {
|
|
|
|
points := []Point{}
|
|
|
|
for _, p := range bp.Points {
|
|
|
|
if p.Timestamp.IsZero() {
|
|
|
|
if bp.Timestamp.IsZero() {
|
|
|
|
p.Timestamp = time.Now()
|
|
|
|
} else {
|
|
|
|
p.Timestamp = bp.Timestamp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if p.Precision == "" && bp.Precision != "" {
|
|
|
|
p.Precision = bp.Precision
|
|
|
|
}
|
|
|
|
p.Timestamp = client.SetPrecision(p.Timestamp, p.Precision)
|
|
|
|
if len(bp.Tags) > 0 {
|
|
|
|
if p.Tags == nil {
|
|
|
|
p.Tags = make(map[string]string)
|
|
|
|
}
|
|
|
|
for k := range bp.Tags {
|
|
|
|
if p.Tags[k] == "" {
|
|
|
|
p.Tags[k] = bp.Tags[k]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Need to convert from a client.Point to a influxdb.Point
|
|
|
|
points = append(points, Point{
|
|
|
|
Name: p.Name,
|
|
|
|
Tags: p.Tags,
|
|
|
|
Timestamp: p.Timestamp,
|
|
|
|
Fields: p.Fields,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return points, nil
|
|
|
|
}
|