Fix meta.Client CreateDatabaseWithRetentionPolicy RPC command
Previously, meta.Client would drop the default retention policy when trying to create a database with a retention policy. The RPC has now been modified to include the desired retention policy in the CreateDatabase command and have it use that retention policy information instead of the default configuration when provided. This also lowers the number of RPC calls for CreateDatabaseWithRetentionPolicy to only a single RPC call instead of two. Protections have also been included so creating a retention policy with different parameters will return an error similar to if you tried to modify the retention policy separately. Fixes #5696.pull/5705/head
parent
94a383e66d
commit
23da067593
|
@ -28,6 +28,7 @@
|
|||
- [#5695](https://github.com/influxdata/influxdb/pull/5695): Remove meta servers from node.json
|
||||
- [#5606](https://github.com/influxdata/influxdb/issues/5606): TSM conversion reproducibly drops data silently
|
||||
- [#5656](https://github.com/influxdata/influxdb/issues/5656): influx\_tsm: panic during conversion
|
||||
- [#5696](https://github.com/influxdata/influxdb/issues/5696): Do not drop the database when creating with a retention policy
|
||||
|
||||
## v0.10.0 [2016-02-04]
|
||||
|
||||
|
|
|
@ -64,9 +64,9 @@ func init() {
|
|||
exp: `{"results":[{}]}`,
|
||||
},
|
||||
&Query{
|
||||
name: "create database with retention duration should not error with existing database with IF NOT EXISTS",
|
||||
name: "create database with retention duration should error if retention policy is different with IF NOT EXISTS",
|
||||
command: `CREATE DATABASE IF NOT EXISTS db1 WITH DURATION 24h`,
|
||||
exp: `{"results":[{}]}`,
|
||||
exp: `{"results":[{"error":"retention policy conflicts with an existing policy"}]}`,
|
||||
},
|
||||
&Query{
|
||||
name: "create database should error IF NOT EXISTS with bad retention duration",
|
||||
|
|
|
@ -343,24 +343,24 @@ func (c *Client) CreateDatabaseWithRetentionPolicy(name string, rpi *RetentionPo
|
|||
return nil, ErrRetentionPolicyDurationTooLow
|
||||
}
|
||||
|
||||
if _, err := c.CreateDatabase(name); err != nil {
|
||||
return nil, err
|
||||
if db, _ := c.Database(name); db != nil {
|
||||
// Check if the retention policy already exists. If it does and matches
|
||||
// the desired retention policy, exit with no error.
|
||||
if rp := db.RetentionPolicy(rpi.Name); rp != nil {
|
||||
if rp.ReplicaN != rpi.ReplicaN || rp.Duration != rpi.Duration {
|
||||
return nil, ErrRetentionPolicyConflict
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.DropRetentionPolicy(name, rpi.Name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := &internal.CreateRetentionPolicyCommand{
|
||||
Database: proto.String(name),
|
||||
cmd := &internal.CreateDatabaseCommand{
|
||||
Name: proto.String(name),
|
||||
RetentionPolicy: rpi.marshal(),
|
||||
}
|
||||
|
||||
if err := c.retryUntilExec(internal.Command_CreateRetentionPolicyCommand, internal.E_CreateRetentionPolicyCommand_Command, cmd); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.SetDefaultRetentionPolicy(name, rpi.Name); err != nil {
|
||||
err := c.retryUntilExec(internal.Command_CreateDatabaseCommand, internal.E_CreateDatabaseCommand_Command, cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,10 @@ var (
|
|||
ErrRetentionPolicyDurationTooLow = errors.New(fmt.Sprintf("retention policy duration must be at least %s",
|
||||
MinRetentionPolicyDuration))
|
||||
|
||||
// ErrRetentionPolicyConflict is returned when creating a retention policy conflicts
|
||||
// with an existing policy.
|
||||
ErrRetentionPolicyConflict = errors.New("retention policy conflicts with an existing policy")
|
||||
|
||||
// ErrReplicationFactorTooLow is returned when the replication factor is not in an
|
||||
// acceptable range.
|
||||
ErrReplicationFactorTooLow = errors.New("replication factor must be greater than 0")
|
||||
|
|
|
@ -174,18 +174,19 @@ func (x *Command_Type) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
|
||||
type Data struct {
|
||||
Term *uint64 `protobuf:"varint,1,req,name=Term" json:"Term,omitempty"`
|
||||
Index *uint64 `protobuf:"varint,2,req,name=Index" json:"Index,omitempty"`
|
||||
ClusterID *uint64 `protobuf:"varint,3,req,name=ClusterID" json:"ClusterID,omitempty"`
|
||||
Nodes []*NodeInfo `protobuf:"bytes,4,rep,name=Nodes" json:"Nodes,omitempty"`
|
||||
Databases []*DatabaseInfo `protobuf:"bytes,5,rep,name=Databases" json:"Databases,omitempty"`
|
||||
Users []*UserInfo `protobuf:"bytes,6,rep,name=Users" json:"Users,omitempty"`
|
||||
MaxNodeID *uint64 `protobuf:"varint,7,req,name=MaxNodeID" json:"MaxNodeID,omitempty"`
|
||||
MaxShardGroupID *uint64 `protobuf:"varint,8,req,name=MaxShardGroupID" json:"MaxShardGroupID,omitempty"`
|
||||
MaxShardID *uint64 `protobuf:"varint,9,req,name=MaxShardID" json:"MaxShardID,omitempty"`
|
||||
DataNodes []*NodeInfo `protobuf:"bytes,10,rep,name=DataNodes" json:"DataNodes,omitempty"`
|
||||
MetaNodes []*NodeInfo `protobuf:"bytes,11,rep,name=MetaNodes" json:"MetaNodes,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Term *uint64 `protobuf:"varint,1,req,name=Term" json:"Term,omitempty"`
|
||||
Index *uint64 `protobuf:"varint,2,req,name=Index" json:"Index,omitempty"`
|
||||
ClusterID *uint64 `protobuf:"varint,3,req,name=ClusterID" json:"ClusterID,omitempty"`
|
||||
Nodes []*NodeInfo `protobuf:"bytes,4,rep,name=Nodes" json:"Nodes,omitempty"`
|
||||
Databases []*DatabaseInfo `protobuf:"bytes,5,rep,name=Databases" json:"Databases,omitempty"`
|
||||
Users []*UserInfo `protobuf:"bytes,6,rep,name=Users" json:"Users,omitempty"`
|
||||
MaxNodeID *uint64 `protobuf:"varint,7,req,name=MaxNodeID" json:"MaxNodeID,omitempty"`
|
||||
MaxShardGroupID *uint64 `protobuf:"varint,8,req,name=MaxShardGroupID" json:"MaxShardGroupID,omitempty"`
|
||||
MaxShardID *uint64 `protobuf:"varint,9,req,name=MaxShardID" json:"MaxShardID,omitempty"`
|
||||
// added for 0.10.0
|
||||
DataNodes []*NodeInfo `protobuf:"bytes,10,rep,name=DataNodes" json:"DataNodes,omitempty"`
|
||||
MetaNodes []*NodeInfo `protobuf:"bytes,11,rep,name=MetaNodes" json:"MetaNodes,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Data) Reset() { *m = Data{} }
|
||||
|
@ -644,6 +645,8 @@ func (m *Command) GetType() Command_Type {
|
|||
return Command_CreateNodeCommand
|
||||
}
|
||||
|
||||
// This isn't used in >= 0.10.0. Kept around for upgrade purposes. Instead
|
||||
// look at CreateDataNodeCommand and CreateMetaNodeCommand
|
||||
type CreateNodeCommand struct {
|
||||
Host *string `protobuf:"bytes,1,req,name=Host" json:"Host,omitempty"`
|
||||
Rand *uint64 `protobuf:"varint,2,req,name=Rand" json:"Rand,omitempty"`
|
||||
|
@ -709,8 +712,9 @@ var E_DeleteNodeCommand_Command = &proto.ExtensionDesc{
|
|||
}
|
||||
|
||||
type CreateDatabaseCommand struct {
|
||||
Name *string `protobuf:"bytes,1,req,name=Name" json:"Name,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Name *string `protobuf:"bytes,1,req,name=Name" json:"Name,omitempty"`
|
||||
RetentionPolicy *RetentionPolicyInfo `protobuf:"bytes,2,opt,name=RetentionPolicy" json:"RetentionPolicy,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *CreateDatabaseCommand) Reset() { *m = CreateDatabaseCommand{} }
|
||||
|
@ -724,6 +728,13 @@ func (m *CreateDatabaseCommand) GetName() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (m *CreateDatabaseCommand) GetRetentionPolicy() *RetentionPolicyInfo {
|
||||
if m != nil {
|
||||
return m.RetentionPolicy
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var E_CreateDatabaseCommand_Command = &proto.ExtensionDesc{
|
||||
ExtendedType: (*Command)(nil),
|
||||
ExtensionType: (*CreateDatabaseCommand)(nil),
|
||||
|
@ -1604,6 +1615,8 @@ func (m *Response) GetIndex() uint64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
// SetMetaNodeCommand is for the initial metanode in a cluster or
|
||||
// if the single host restarts and its hostname changes, this will update it
|
||||
type SetMetaNodeCommand struct {
|
||||
HTTPAddr *string `protobuf:"bytes,1,req,name=HTTPAddr" json:"HTTPAddr,omitempty"`
|
||||
TCPAddr *string `protobuf:"bytes,2,req,name=TCPAddr" json:"TCPAddr,omitempty"`
|
||||
|
|
|
@ -120,12 +120,12 @@ message Command {
|
|||
CreateSubscriptionCommand = 21;
|
||||
DropSubscriptionCommand = 22;
|
||||
RemovePeerCommand = 23;
|
||||
CreateMetaNodeCommand = 24;
|
||||
CreateDataNodeCommand = 25;
|
||||
UpdateDataNodeCommand = 26;
|
||||
DeleteMetaNodeCommand = 27;
|
||||
DeleteDataNodeCommand = 28;
|
||||
SetMetaNodeCommand = 29;
|
||||
CreateMetaNodeCommand = 24;
|
||||
CreateDataNodeCommand = 25;
|
||||
UpdateDataNodeCommand = 26;
|
||||
DeleteMetaNodeCommand = 27;
|
||||
DeleteDataNodeCommand = 28;
|
||||
SetMetaNodeCommand = 29;
|
||||
}
|
||||
|
||||
required Type type = 1;
|
||||
|
@ -154,6 +154,7 @@ message CreateDatabaseCommand {
|
|||
optional CreateDatabaseCommand command = 103;
|
||||
}
|
||||
required string Name = 1;
|
||||
optional RetentionPolicyInfo RetentionPolicy = 2;
|
||||
}
|
||||
|
||||
message DropDatabaseCommand {
|
||||
|
@ -355,7 +356,7 @@ message DeleteDataNodeCommand {
|
|||
extend Command {
|
||||
optional DeleteDataNodeCommand command = 128;
|
||||
}
|
||||
required uint64 ID = 1;
|
||||
required uint64 ID = 1;
|
||||
}
|
||||
|
||||
message Response {
|
||||
|
|
|
@ -208,7 +208,24 @@ func (fsm *storeFSM) applyCreateDatabaseCommand(cmd *internal.Command) interface
|
|||
}
|
||||
|
||||
s := (*store)(fsm)
|
||||
if s.config.RetentionAutoCreate {
|
||||
if rpi := v.GetRetentionPolicy(); rpi != nil {
|
||||
if err := other.CreateRetentionPolicy(v.GetName(), &RetentionPolicyInfo{
|
||||
Name: rpi.GetName(),
|
||||
ReplicaN: int(rpi.GetReplicaN()),
|
||||
Duration: time.Duration(rpi.GetDuration()),
|
||||
ShardGroupDuration: time.Duration(rpi.GetShardGroupDuration()),
|
||||
}); err != nil {
|
||||
if err == ErrRetentionPolicyExists {
|
||||
return ErrRetentionPolicyConflict
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Set it as the default retention policy.
|
||||
if err := other.SetDefaultRetentionPolicy(v.GetName(), rpi.GetName()); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if s.config.RetentionAutoCreate {
|
||||
// Read node count.
|
||||
// Retention policies must be fully replicated.
|
||||
replicaN := len(other.DataNodes)
|
||||
|
|
Loading…
Reference in New Issue