log_entry.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package raft
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "github.com/coreos/etcd/third_party/code.google.com/p/gogoprotobuf/proto"
  8. "github.com/coreos/etcd/third_party/github.com/goraft/raft/protobuf"
  9. )
  10. // A log entry stores a single item in the log.
  11. type LogEntry struct {
  12. pb *protobuf.LogEntry
  13. Position int64 // position in the log file
  14. log *Log
  15. event *ev
  16. }
  17. // Creates a new log entry associated with a log.
  18. func newLogEntry(log *Log, event *ev, index uint64, term uint64, command Command) (*LogEntry, error) {
  19. var buf bytes.Buffer
  20. var commandName string
  21. if command != nil {
  22. commandName = command.CommandName()
  23. if encoder, ok := command.(CommandEncoder); ok {
  24. if err := encoder.Encode(&buf); err != nil {
  25. return nil, err
  26. }
  27. } else {
  28. if err := json.NewEncoder(&buf).Encode(command); err != nil {
  29. return nil, err
  30. }
  31. }
  32. }
  33. pb := &protobuf.LogEntry{
  34. Index: proto.Uint64(index),
  35. Term: proto.Uint64(term),
  36. CommandName: proto.String(commandName),
  37. Command: buf.Bytes(),
  38. }
  39. e := &LogEntry{
  40. pb: pb,
  41. log: log,
  42. event: event,
  43. }
  44. return e, nil
  45. }
  46. func (e *LogEntry) Index() uint64 {
  47. return e.pb.GetIndex()
  48. }
  49. func (e *LogEntry) Term() uint64 {
  50. return e.pb.GetTerm()
  51. }
  52. func (e *LogEntry) CommandName() string {
  53. return e.pb.GetCommandName()
  54. }
  55. func (e *LogEntry) Command() []byte {
  56. return e.pb.GetCommand()
  57. }
  58. // Encodes the log entry to a buffer. Returns the number of bytes
  59. // written and any error that may have occurred.
  60. func (e *LogEntry) Encode(w io.Writer) (int, error) {
  61. b, err := proto.Marshal(e.pb)
  62. if err != nil {
  63. return -1, err
  64. }
  65. if _, err = fmt.Fprintf(w, "%8x\n", len(b)); err != nil {
  66. return -1, err
  67. }
  68. return w.Write(b)
  69. }
  70. // Decodes the log entry from a buffer. Returns the number of bytes read and
  71. // any error that occurs.
  72. func (e *LogEntry) Decode(r io.Reader) (int, error) {
  73. var length int
  74. _, err := fmt.Fscanf(r, "%8x\n", &length)
  75. if err != nil {
  76. return -1, err
  77. }
  78. data := make([]byte, length)
  79. _, err = io.ReadFull(r, data)
  80. if err != nil {
  81. return -1, err
  82. }
  83. if err = proto.Unmarshal(data, e.pb); err != nil {
  84. return -1, err
  85. }
  86. return length + 8 + 1, nil
  87. }