github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2013/distsys/replread.go (about) 1 // +build OMIT 2 3 package main 4 5 import ( 6 "fmt" 7 "math" 8 "math/rand" 9 "sync" 10 "time" 11 ) 12 13 const ( 14 F = 2 15 N = 5 16 ReadQuorum = F + 1 17 WriteQuorum = N - F 18 ) 19 20 var delay = false 21 22 type Server struct { 23 mu sync.Mutex 24 data map[string]*Data 25 } 26 27 type Data struct { 28 Key string 29 Value string 30 Time time.Time 31 } 32 33 func (srv *Server) Delay() { 34 if delay == false { 35 return 36 } 37 time.Sleep(time.Duration(math.Abs(rand.NormFloat64()*1e9 + 0.1e9))) 38 } 39 40 func (srv *Server) Write(req *Data) { 41 t0 := time.Now() 42 defer func() { 43 if delay { 44 fmt.Printf("write took %.3f seconds\n", time.Since(t0).Seconds()) 45 } 46 }() 47 48 srv.mu.Lock() 49 defer srv.mu.Unlock() 50 srv.Delay() 51 52 if srv.data == nil { 53 srv.data = make(map[string]*Data) 54 } 55 if d := srv.data[req.Key]; d == nil || d.Time.Before(req.Time) { 56 srv.data[req.Key] = req 57 } 58 } 59 60 func (srv *Server) Read(key string) *Data { 61 t0 := time.Now() 62 defer func() { 63 fmt.Printf("read took %.3f seconds\n", time.Since(t0).Seconds()) 64 }() 65 66 srv.mu.Lock() 67 defer srv.mu.Unlock() 68 srv.Delay() 69 70 return srv.data[key] 71 } 72 73 func better(x, y *Data) *Data { 74 if x == nil { 75 return y 76 } 77 if y == nil || y.Time.Before(x.Time) { 78 return x 79 } 80 return y 81 } 82 83 func Write(req *Data) { 84 t0 := time.Now() 85 done := make(chan bool, len(servers)) 86 87 for _, srv := range servers { 88 go func(srv *Server) { 89 srv.Write(req) 90 done <- true 91 }(srv) 92 } 93 94 for n := 0; n < WriteQuorum; n++ { 95 <-done 96 } 97 98 if delay { 99 fmt.Printf("write committed at %.3f seconds\n", time.Since(t0).Seconds()) 100 } 101 for n := WriteQuorum; n < N; n++ { 102 <-done 103 } 104 if delay { 105 fmt.Printf("all replicas written at %.3f seconds\n", time.Since(t0).Seconds()) 106 } 107 } 108 109 func Read(key string) { 110 t0 := time.Now() 111 replies := make(chan *Data, len(servers)) 112 113 for _, srv := range servers { 114 go func(srv *Server) { 115 replies <- srv.Read(key) 116 }(srv) 117 } 118 119 var d *Data 120 for n := 0; n < ReadQuorum; n++ { 121 d = better(d, <-replies) 122 } 123 124 if delay { 125 fmt.Printf("read committed at %.3f seconds\n", time.Since(t0).Seconds()) 126 } 127 128 for n := ReadQuorum; n < N; n++ { 129 <-replies 130 } 131 if delay { 132 fmt.Printf("all replicas read at %.3f seconds\n", time.Since(t0).Seconds()) 133 } 134 } 135 136 var servers []*Server 137 138 func main() { 139 servers = make([]*Server, N) 140 for i := range servers { 141 servers[i] = new(Server) 142 } 143 144 rand.Seed(time.Now().UnixNano()) 145 146 delay = false 147 Write(&Data{"hello", "there", time.Now()}) 148 time.Sleep(1 * time.Millisecond) 149 150 Write(&Data{"hello", "world", time.Now()}) 151 152 delay = true 153 Read("hello") 154 }