63 lines
1.6 KiB
Go
63 lines
1.6 KiB
Go
package raft
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"math/rand"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// uint64Slice implements sort interface
|
|
type uint64Slice []uint64
|
|
|
|
func (p uint64Slice) Len() int { return len(p) }
|
|
func (p uint64Slice) Less(i, j int) bool { return p[i] < p[j] }
|
|
func (p uint64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
|
|
|
// WriteFile writes data to a file named by filename.
|
|
// If the file does not exist, WriteFile creates it with permissions perm;
|
|
// otherwise WriteFile truncates it before writing.
|
|
// This is copied from ioutil.WriteFile with the addition of a Sync call to
|
|
// ensure the data reaches the disk.
|
|
func writeFileSynced(filename string, data []byte, perm os.FileMode) error {
|
|
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close() // Idempotent
|
|
|
|
n, err := f.Write(data)
|
|
if err == nil && n < len(data) {
|
|
return io.ErrShortWrite
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = f.Sync(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return f.Close()
|
|
}
|
|
|
|
// Waits for a random time between two durations and sends the current time on
|
|
// the returned channel.
|
|
func afterBetween(min time.Duration, max time.Duration) <-chan time.Time {
|
|
rand := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
d, delta := min, (max - min)
|
|
if delta > 0 {
|
|
d += time.Duration(rand.Int63n(int64(delta)))
|
|
}
|
|
return time.After(d)
|
|
}
|
|
|
|
// TODO(xiangli): Remove assertions when we reach version 1.0
|
|
|
|
// _assert will panic with a given formatted message if the given condition is false.
|
|
func _assert(condition bool, msg string, v ...interface{}) {
|
|
if !condition {
|
|
panic(fmt.Sprintf("assertion failed: "+msg, v...))
|
|
}
|
|
}
|