main.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright 2015 CoreOS, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package main
  15. import (
  16. "errors"
  17. "flag"
  18. "fmt"
  19. "log"
  20. "path"
  21. etcdserverpb "github.com/coreos/etcd/etcdserver/etcdserverpb"
  22. "github.com/coreos/etcd/migrate"
  23. "github.com/coreos/etcd/pkg/types"
  24. raftpb "github.com/coreos/etcd/raft/raftpb"
  25. "github.com/coreos/etcd/wal"
  26. "github.com/coreos/etcd/wal/walpb"
  27. )
  28. func walDir5(dataDir string) string {
  29. return path.Join(dataDir, "wal")
  30. }
  31. func logFile4(dataDir string) string {
  32. return path.Join(dataDir, "log")
  33. }
  34. func main() {
  35. version := flag.Int("version", 5, "4 or 5")
  36. from := flag.String("data-dir", "", "")
  37. flag.Parse()
  38. if *from == "" {
  39. log.Fatal("Must provide -data-dir flag")
  40. }
  41. var ents []raftpb.Entry
  42. var err error
  43. switch *version {
  44. case 4:
  45. ents, err = dump4(*from)
  46. case 5:
  47. ents, err = dump5(*from)
  48. default:
  49. err = errors.New("value of -version flag must be 4 or 5")
  50. }
  51. if err != nil {
  52. log.Fatalf("Failed decoding log: %v", err)
  53. }
  54. for _, e := range ents {
  55. msg := fmt.Sprintf("%2d %5d: ", e.Term, e.Index)
  56. switch e.Type {
  57. case raftpb.EntryNormal:
  58. msg = fmt.Sprintf("%s norm", msg)
  59. var r etcdserverpb.Request
  60. if err := r.Unmarshal(e.Data); err != nil {
  61. msg = fmt.Sprintf("%s ???", msg)
  62. } else {
  63. msg = fmt.Sprintf("%s %s %s %s", msg, r.Method, r.Path, r.Val)
  64. }
  65. case raftpb.EntryConfChange:
  66. msg = fmt.Sprintf("%s conf", msg)
  67. var r raftpb.ConfChange
  68. if err := r.Unmarshal(e.Data); err != nil {
  69. msg = fmt.Sprintf("%s ???", msg)
  70. } else {
  71. msg = fmt.Sprintf("%s %s %s %s", msg, r.Type, types.ID(r.NodeID), r.Context)
  72. }
  73. }
  74. fmt.Println(msg)
  75. }
  76. }
  77. func dump4(dataDir string) ([]raftpb.Entry, error) {
  78. lf4 := logFile4(dataDir)
  79. ents, err := migrate.DecodeLog4FromFile(lf4)
  80. if err != nil {
  81. return nil, err
  82. }
  83. return migrate.Entries4To2(ents)
  84. }
  85. func dump5(dataDir string) ([]raftpb.Entry, error) {
  86. wd5 := walDir5(dataDir)
  87. if !wal.Exist(wd5) {
  88. return nil, fmt.Errorf("No wal exists at %s", wd5)
  89. }
  90. w, err := wal.Open(wd5, walpb.Snapshot{})
  91. if err != nil {
  92. return nil, err
  93. }
  94. defer w.Close()
  95. _, _, ents, err := w.ReadAll()
  96. return ents, err
  97. }