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  }