diff --git a/etcd/v2_apply.go b/etcd/v2_apply.go index 4a494201490..ed9eefde807 100644 --- a/etcd/v2_apply.go +++ b/etcd/v2_apply.go @@ -17,9 +17,9 @@ limitations under the License. package etcd import ( - "encoding/json" "fmt" "log" + "time" "github.com/coreos/etcd/raft" "github.com/coreos/etcd/store" @@ -30,29 +30,29 @@ func (p *participant) v2apply(index int64, ent raft.Entry) { var e *store.Event var err error - cmd := new(cmd) - if err := json.Unmarshal(ent.Data, cmd); err != nil { + var cmd Cmd + if err := cmd.Unmarshal(ent.Data); err != nil { log.Printf("id=%x participant.store.apply decodeErr=\"%v\"\n", p.id, err) return } switch cmd.Type { - case "set": - e, err = p.Store.Set(cmd.Key, cmd.Dir, cmd.Value, cmd.Time) - case "update": - e, err = p.Store.Update(cmd.Key, cmd.Value, cmd.Time) - case "create", "unique": - e, err = p.Store.Create(cmd.Key, cmd.Dir, cmd.Value, cmd.Unique, cmd.Time) - case "delete": - e, err = p.Store.Delete(cmd.Key, cmd.Dir, cmd.Recursive) - case "cad": - e, err = p.Store.CompareAndDelete(cmd.Key, cmd.PrevValue, cmd.PrevIndex) - case "cas": - e, err = p.Store.CompareAndSwap(cmd.Key, cmd.PrevValue, cmd.PrevIndex, cmd.Value, cmd.Time) - case "quorumGet": - e, err = p.Store.Get(cmd.Key, cmd.Recursive, cmd.Sorted) - case "sync": - p.Store.DeleteExpiredKeys(cmd.Time) + case stset: + e, err = p.Store.Set(cmd.Key, *cmd.Dir, *cmd.Value, mustUnmarshalTime(cmd.Time)) + case stupdate: + e, err = p.Store.Update(cmd.Key, *cmd.Value, mustUnmarshalTime(cmd.Time)) + case stcreate: + e, err = p.Store.Create(cmd.Key, *cmd.Dir, *cmd.Value, *cmd.Unique, mustUnmarshalTime(cmd.Time)) + case stdelete: + e, err = p.Store.Delete(cmd.Key, *cmd.Dir, *cmd.Recursive) + case stcad: + e, err = p.Store.CompareAndDelete(cmd.Key, *cmd.PrevValue, *cmd.PrevIndex) + case stcas: + e, err = p.Store.CompareAndSwap(cmd.Key, *cmd.PrevValue, *cmd.PrevIndex, *cmd.Value, mustUnmarshalTime(cmd.Time)) + case stqget: + e, err = p.Store.Get(cmd.Key, *cmd.Recursive, *cmd.Sorted) + case stsync: + p.Store.DeleteExpiredKeys(mustUnmarshalTime(cmd.Time)) return default: log.Printf("id=%x participant.store.apply err=\"unexpected command type %s\"\n", p.id, cmd.Type) @@ -81,3 +81,19 @@ func (p *participant) v2apply(index int64, ent raft.Entry) { p.node.result[w] <- ret delete(p.node.result, w) } + +func mustMarshalTime(t *time.Time) []byte { + b, err := t.MarshalBinary() + if err != nil { + panic(err) + } + return b +} + +func mustUnmarshalTime(b []byte) time.Time { + var time time.Time + if err := time.UnmarshalBinary(b); err != nil { + panic(err) + } + return time +} diff --git a/etcd/v2_raft.go b/etcd/v2_raft.go index 47707d547e0..8b5f5af5075 100644 --- a/etcd/v2_raft.go +++ b/etcd/v2_raft.go @@ -17,7 +17,6 @@ limitations under the License. package etcd import ( - "encoding/json" "fmt" "time" @@ -54,8 +53,9 @@ func (r *v2Raft) Sync() { if !r.Node.IsLeader() { return } - sync := &cmd{Type: "sync", Time: time.Now()} - data, err := json.Marshal(sync) + t := time.Now() + sync := &Cmd{Type: stsync, Time: mustMarshalTime(&t)} + data, err := sync.Marshal() if err != nil { panic(err) } diff --git a/etcd/v2_store.go b/etcd/v2_store.go index 59762047aa5..e8ca5dfaad7 100644 --- a/etcd/v2_store.go +++ b/etcd/v2_store.go @@ -17,63 +17,59 @@ limitations under the License. package etcd import ( - "encoding/json" "fmt" "time" "github.com/coreos/etcd/store" ) -type cmd struct { - Type string - Key string - Value string - PrevValue string - PrevIndex uint64 - Dir bool - Recursive bool - Unique bool - Sorted bool - Time time.Time -} +const ( + stset = iota + stcreate + stupdate + stcas + stdelete + stcad + stqget + stsync +) func (p *participant) Set(key string, dir bool, value string, expireTime time.Time) (*store.Event, error) { - set := &cmd{Type: "set", Key: key, Dir: dir, Value: value, Time: expireTime} + set := &Cmd{Type: stset, Key: key, Dir: &dir, Value: &value, Time: mustMarshalTime(&expireTime)} return p.do(set) } func (p *participant) Create(key string, dir bool, value string, expireTime time.Time, unique bool) (*store.Event, error) { - create := &cmd{Type: "create", Key: key, Dir: dir, Value: value, Time: expireTime, Unique: unique} + create := &Cmd{Type: stcreate, Key: key, Dir: &dir, Value: &value, Time: mustMarshalTime(&expireTime), Unique: &unique} return p.do(create) } func (p *participant) Update(key string, value string, expireTime time.Time) (*store.Event, error) { - update := &cmd{Type: "update", Key: key, Value: value, Time: expireTime} + update := &Cmd{Type: stupdate, Key: key, Value: &value, Time: mustMarshalTime(&expireTime)} return p.do(update) } func (p *participant) CAS(key, value, prevValue string, prevIndex uint64, expireTime time.Time) (*store.Event, error) { - cas := &cmd{Type: "cas", Key: key, Value: value, PrevValue: prevValue, PrevIndex: prevIndex, Time: expireTime} + cas := &Cmd{Type: stcas, Key: key, Value: &value, PrevValue: &prevValue, PrevIndex: &prevIndex, Time: mustMarshalTime(&expireTime)} return p.do(cas) } func (p *participant) Delete(key string, dir, recursive bool) (*store.Event, error) { - d := &cmd{Type: "delete", Key: key, Dir: dir, Recursive: recursive} + d := &Cmd{Type: stdelete, Key: key, Dir: &dir, Recursive: &recursive} return p.do(d) } func (p *participant) CAD(key string, prevValue string, prevIndex uint64) (*store.Event, error) { - cad := &cmd{Type: "cad", Key: key, PrevValue: prevValue, PrevIndex: prevIndex} + cad := &Cmd{Type: stcad, Key: key, PrevValue: &prevValue, PrevIndex: &prevIndex} return p.do(cad) } - func (p *participant) QuorumGet(key string, recursive, sorted bool) (*store.Event, error) { - get := &cmd{Type: "quorumGet", Key: key, Recursive: recursive, Sorted: sorted} + get := &Cmd{Type: stqget, Key: key, Recursive: &recursive, Sorted: &sorted} return p.do(get) } -func (p *participant) do(c *cmd) (*store.Event, error) { - data, err := json.Marshal(c) +func (p *participant) do(c *Cmd) (*store.Event, error) { + data, err := c.Marshal() if err != nil { panic(err) } diff --git a/etcd/v2_store_cmd.pb.go b/etcd/v2_store_cmd.pb.go new file mode 100644 index 00000000000..2747a241ee4 --- /dev/null +++ b/etcd/v2_store_cmd.pb.go @@ -0,0 +1,454 @@ +// Code generated by protoc-gen-gogo. +// source: v2_store_cmd.proto +// DO NOT EDIT! + +/* + Package etcd is a generated protocol buffer package. + + It is generated from these files: + v2_store_cmd.proto + + It has these top-level messages: + Cmd +*/ +package etcd + +import proto "code.google.com/p/gogoprotobuf/proto" +import json "encoding/json" +import math "math" + +// discarding unused import gogoproto "code.google.com/p/gogoprotobuf/gogoproto/gogo.pb" + +import io "io" +import code_google_com_p_gogoprotobuf_proto "code.google.com/p/gogoprotobuf/proto" + +// Reference proto, json, and math imports to suppress error if they are not otherwise used. +var _ = proto.Marshal +var _ = &json.SyntaxError{} +var _ = math.Inf + +type Cmd struct { + Type int32 `protobuf:"varint,1,req,name=type" json:"type"` + Key string `protobuf:"bytes,2,req,name=key" json:"key"` + Value *string `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"` + PrevValue *string `protobuf:"bytes,4,opt,name=prevValue" json:"prevValue,omitempty"` + PrevIndex *uint64 `protobuf:"varint,5,opt,name=prevIndex" json:"prevIndex,omitempty"` + Dir *bool `protobuf:"varint,6,opt,name=dir" json:"dir,omitempty"` + Recursive *bool `protobuf:"varint,7,opt,name=recursive" json:"recursive,omitempty"` + Unique *bool `protobuf:"varint,8,opt,name=unique" json:"unique,omitempty"` + Sorted *bool `protobuf:"varint,9,opt,name=sorted" json:"sorted,omitempty"` + Time []byte `protobuf:"bytes,10,opt,name=time" json:"time,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Cmd) Reset() { *m = Cmd{} } +func (m *Cmd) String() string { return proto.CompactTextString(m) } +func (*Cmd) ProtoMessage() {} + +func init() { +} +func (m *Cmd) Unmarshal(data []byte) error { + l := len(data) + index := 0 + for index < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + switch fieldNum { + case 1: + if wireType != 0 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + m.Type |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + postIndex := index + int(stringLen) + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(data[index:postIndex]) + index = postIndex + case 3: + if wireType != 2 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + postIndex := index + int(stringLen) + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(data[index:postIndex]) + m.Value = &s + index = postIndex + case 4: + if wireType != 2 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + postIndex := index + int(stringLen) + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(data[index:postIndex]) + m.PrevValue = &s + index = postIndex + case 5: + if wireType != 0 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + var v uint64 + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + v |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.PrevIndex = &v + case 6: + if wireType != 0 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + var v int + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.Dir = &b + case 7: + if wireType != 0 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + var v int + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.Recursive = &b + case 8: + if wireType != 0 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + var v int + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.Unique = &b + case 9: + if wireType != 0 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + var v int + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.Sorted = &b + case 10: + if wireType != 2 { + return code_google_com_p_gogoprotobuf_proto.ErrWrongType + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if index >= l { + return io.ErrUnexpectedEOF + } + b := data[index] + index++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + postIndex := index + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Time = append(m.Time, data[index:postIndex]...) + index = postIndex + default: + var sizeOfWire int + for { + sizeOfWire++ + wire >>= 7 + if wire == 0 { + break + } + } + index -= sizeOfWire + skippy, err := code_google_com_p_gogoprotobuf_proto.Skip(data[index:]) + if err != nil { + return err + } + if (index + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, data[index:index+skippy]...) + index += skippy + } + } + return nil +} +func (m *Cmd) Size() (n int) { + var l int + _ = l + n += 1 + sovV2StoreCmd(uint64(uint32(m.Type))) + l = len(m.Key) + n += 1 + l + sovV2StoreCmd(uint64(l)) + if m.Value != nil { + l = len(*m.Value) + n += 1 + l + sovV2StoreCmd(uint64(l)) + } + if m.PrevValue != nil { + l = len(*m.PrevValue) + n += 1 + l + sovV2StoreCmd(uint64(l)) + } + if m.PrevIndex != nil { + n += 1 + sovV2StoreCmd(uint64(*m.PrevIndex)) + } + if m.Dir != nil { + n += 2 + } + if m.Recursive != nil { + n += 2 + } + if m.Unique != nil { + n += 2 + } + if m.Sorted != nil { + n += 2 + } + if m.Time != nil { + l = len(m.Time) + n += 1 + l + sovV2StoreCmd(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func sovV2StoreCmd(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozV2StoreCmd(x uint64) (n int) { + return sovV2StoreCmd(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Cmd) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *Cmd) MarshalTo(data []byte) (n int, err error) { + var i int + _ = i + var l int + _ = l + data[i] = 0x8 + i++ + i = encodeVarintV2StoreCmd(data, i, uint64(uint32(m.Type))) + data[i] = 0x12 + i++ + i = encodeVarintV2StoreCmd(data, i, uint64(len(m.Key))) + i += copy(data[i:], m.Key) + if m.Value != nil { + data[i] = 0x1a + i++ + i = encodeVarintV2StoreCmd(data, i, uint64(len(*m.Value))) + i += copy(data[i:], *m.Value) + } + if m.PrevValue != nil { + data[i] = 0x22 + i++ + i = encodeVarintV2StoreCmd(data, i, uint64(len(*m.PrevValue))) + i += copy(data[i:], *m.PrevValue) + } + if m.PrevIndex != nil { + data[i] = 0x28 + i++ + i = encodeVarintV2StoreCmd(data, i, uint64(*m.PrevIndex)) + } + if m.Dir != nil { + data[i] = 0x30 + i++ + if *m.Dir { + data[i] = 1 + } else { + data[i] = 0 + } + i++ + } + if m.Recursive != nil { + data[i] = 0x38 + i++ + if *m.Recursive { + data[i] = 1 + } else { + data[i] = 0 + } + i++ + } + if m.Unique != nil { + data[i] = 0x40 + i++ + if *m.Unique { + data[i] = 1 + } else { + data[i] = 0 + } + i++ + } + if m.Sorted != nil { + data[i] = 0x48 + i++ + if *m.Sorted { + data[i] = 1 + } else { + data[i] = 0 + } + i++ + } + if m.Time != nil { + data[i] = 0x52 + i++ + i = encodeVarintV2StoreCmd(data, i, uint64(len(m.Time))) + i += copy(data[i:], m.Time) + } + if m.XXX_unrecognized != nil { + i += copy(data[i:], m.XXX_unrecognized) + } + return i, nil +} +func encodeFixed64V2StoreCmd(data []byte, offset int, v uint64) int { + data[offset] = uint8(v) + data[offset+1] = uint8(v >> 8) + data[offset+2] = uint8(v >> 16) + data[offset+3] = uint8(v >> 24) + data[offset+4] = uint8(v >> 32) + data[offset+5] = uint8(v >> 40) + data[offset+6] = uint8(v >> 48) + data[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32V2StoreCmd(data []byte, offset int, v uint32) int { + data[offset] = uint8(v) + data[offset+1] = uint8(v >> 8) + data[offset+2] = uint8(v >> 16) + data[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintV2StoreCmd(data []byte, offset int, v uint64) int { + for v >= 1<<7 { + data[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + data[offset] = uint8(v) + return offset + 1 +} diff --git a/etcd/v2_store_cmd.proto b/etcd/v2_store_cmd.proto new file mode 100644 index 00000000000..73ff0615876 --- /dev/null +++ b/etcd/v2_store_cmd.proto @@ -0,0 +1,21 @@ +package etcd; + +import "code.google.com/p/gogoprotobuf/gogoproto/gogo.proto"; + +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.goproto_getters_all) = false; + +message cmd { + required int32 type = 1 [(gogoproto.nullable) = false]; + required string key = 2 [(gogoproto.nullable) = false]; + optional string value = 3; + optional string prevValue = 4; + optional uint64 prevIndex = 5; + optional bool dir = 6; + optional bool recursive = 7; + optional bool unique = 8; + optional bool sorted = 9; + optional bytes time = 10; +}