log_entry.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. json.NewEncoder(&buf).Encode(command)
  29. }
  30. }
  31. pb := &protobuf.LogEntry{
  32. Index: proto.Uint64(index),
  33. Term: proto.Uint64(term),
  34. CommandName: proto.String(commandName),
  35. Command: buf.Bytes(),
  36. }
  37. e := &LogEntry{
  38. pb: pb,
  39. log: log,
  40. event: event,
  41. }
  42. return e, nil
  43. }
  44. func (e *LogEntry) Index() uint64 {
  45. return e.pb.GetIndex()
  46. }
  47. func (e *LogEntry) Term() uint64 {
  48. return e.pb.GetTerm()
  49. }
  50. func (e *LogEntry) CommandName() string {
  51. return e.pb.GetCommandName()
  52. }
  53. func (e *LogEntry) Command() []byte {
  54. return e.pb.GetCommand()
  55. }
  56. // Encodes the log entry to a buffer. Returns the number of bytes
  57. // written and any error that may have occurred.
  58. func (e *LogEntry) Encode(w io.Writer) (int, error) {
  59. b, err := proto.Marshal(e.pb)
  60. if err != nil {
  61. return -1, err
  62. }
  63. if _, err = fmt.Fprintf(w, "%8x\n", len(b)); err != nil {
  64. return -1, err
  65. }
  66. return w.Write(b)
  67. }
  68. // Decodes the log entry from a buffer. Returns the number of bytes read and
  69. // any error that occurs.
  70. func (e *LogEntry) Decode(r io.Reader) (int, error) {
  71. var length int
  72. _, err := fmt.Fscanf(r, "%8x\n", &length)
  73. if err != nil {
  74. return -1, err
  75. }
  76. data := make([]byte, length)
  77. _, err = io.ReadFull(r, data)
  78. if err != nil {
  79. return -1, err
  80. }
  81. if err = proto.Unmarshal(data, e.pb); err != nil {
  82. return -1, err
  83. }
  84. return length + 8 + 1, nil
  85. }