github.com/mre-fog/trillianxx@v1.1.2-0.20180615153820-ae375a99d36a/docs/storage/commit_log/main.go (about) 1 // Copyright 2017 Google Inc. All Rights Reserved. 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 15 // The commit_log binary runs a simulation of the design for a commit-log 16 // based signer, with a simulated Kafka-like interface and a simulated 17 // master election package (which can be triggered to incorrectly report 18 // multiple masters), and with the core algorithm in the signer code. 19 // glog.Warning is used throughout for unexpected-but-recoverable situations, 20 // whereas glog.Error is used for any situation that would indicate data 21 // corruption. 22 package main 23 24 import ( 25 "flag" 26 "fmt" 27 "math/rand" 28 "sync" 29 "time" 30 31 "github.com/golang/glog" 32 "github.com/google/trillian/docs/storage/commit_log/signer" 33 "github.com/google/trillian/docs/storage/commit_log/simelection" 34 "github.com/google/trillian/docs/storage/commit_log/simkafka" 35 ) 36 37 var ( 38 runElections = flag.Bool("run_elections", false, "Whether to use mastership election; if false, signers run in parallel") 39 signerCount = flag.Int("signer_count", 3, "Number of parallel signers to run") 40 leafInterval = flag.Duration("leaf_interval", 500*time.Millisecond, "Period between added leaves") 41 eventInterval = flag.Duration("event_interval", 1*time.Second, "Interval between events") 42 masterChangePercent = flag.Int("master_change", 20, "Percent chance of a change of master") 43 dualMasterPercent = flag.Int("dual_master", 8, "Percent chance of a dual master") 44 leafTogglePercent = flag.Int("leaf_toggle", 10, "Percent chance of toggling leaf generation") 45 ) 46 47 var names = []string{"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"} 48 49 func signerName(i int) string { 50 if i < len(names) { 51 return names[i] 52 } 53 return fmt.Sprintf("signer%d", i) 54 } 55 56 func increment(s string) string { 57 if len(s) == 0 { 58 return "A" 59 } 60 offset := len(s) - 1 61 char := s[offset] 62 var prefix string 63 if len(s) > 1 { 64 prefix = s[0:offset] 65 } 66 if char < 'Z' { 67 char++ 68 return string(append([]byte(prefix), char)) 69 } 70 return string(append([]byte(increment(prefix)), 'A')) 71 } 72 73 type lockedBool struct { 74 mu sync.RWMutex 75 val bool 76 } 77 78 func (ab *lockedBool) Get() bool { 79 ab.mu.RLock() 80 defer ab.mu.RUnlock() 81 return ab.val 82 } 83 func (ab *lockedBool) Set(v bool) { 84 ab.mu.Lock() 85 defer ab.mu.Unlock() 86 ab.val = v 87 } 88 89 func main() { 90 flag.Parse() 91 defer glog.Flush() 92 93 epochMillis := time.Now().UnixNano() / int64(time.Millisecond) 94 95 // Add leaves forever 96 generateLeaves := lockedBool{val: true} 97 go func() { 98 nextLeaf := "A" 99 for { 100 time.Sleep(*leafInterval) 101 if generateLeaves.Get() { 102 simkafka.Append("Leaves/<treeID>", nextLeaf) 103 nextLeaf = increment(nextLeaf) 104 } 105 } 106 }() 107 108 // Run a few signers forever 109 var election *simelection.Election 110 if *runElections { 111 election = &simelection.Election{} 112 } else { 113 // Mastership manipulations are irrelevant if no elections. 114 *masterChangePercent = 0 115 *dualMasterPercent = 0 116 } 117 signers := []*signer.Signer{} 118 for ii := 0; ii < *signerCount; ii++ { 119 signers = append(signers, signer.New(signerName(ii), election, epochMillis)) 120 } 121 for _, s := range signers { 122 go func(s *signer.Signer) { 123 for { 124 time.Sleep(1 * time.Second) 125 s.Run() 126 } 127 }(s) 128 } 129 130 for { 131 choice := rand.Intn(100) 132 switch { 133 case choice < *masterChangePercent: 134 which := rand.Intn(len(signers)) 135 who := signers[which].Name 136 glog.V(1).Infof("EVENT: Move mastership from %v to [%v]", election.Masters(), who) 137 election.SetMaster(who) 138 case choice < (*masterChangePercent + *dualMasterPercent): 139 if len(election.Masters()) > 1 { 140 // Already in dual-master mode 141 break 142 } 143 which1 := rand.Intn(len(signers)) 144 who1 := signers[which1].Name 145 which2 := rand.Intn(len(signers)) 146 who2 := signers[which2].Name 147 masters := []string{who1, who2} 148 glog.V(1).Infof("EVENT: Make multiple mastership, from %v to %v", election.Masters(), masters) 149 election.SetMasters(masters) 150 case choice < (*masterChangePercent + *dualMasterPercent + *leafTogglePercent): 151 val := generateLeaves.Get() 152 glog.V(1).Infof("EVENT: Toggle leaf generation from %v to %v", val, !val) 153 generateLeaves.Set(!val) 154 } 155 156 time.Sleep(*eventInterval) 157 158 // Show current status 159 output := simkafka.Status() 160 for _, s := range signers { 161 output += s.String() 162 } 163 fmt.Printf("\n%s\n", output) 164 } 165 }