/
frontend.go
184 lines (142 loc) · 4.72 KB
/
frontend.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package server
import (
"bufio"
"fmt"
"net"
"os"
"sync"
logger "github.com/Blyth77/DISYS_MiniProject03/logger"
protos "github.com/Blyth77/DISYS_MiniProject03/proto"
"google.golang.org/grpc"
)
var (
ID int32
currentHighestBidder = HighestBidder{}
)
type Server struct {
protos.UnimplementedAuctionhouseServiceServer
auctioneer sync.Map
}
type sub struct {
streamBid protos.AuctionhouseService_BidServer
finished chan<- bool
}
type HighestBidder struct {
HighestBidAmount int32
HighestBidderID int32
streamBid protos.AuctionhouseService_BidServer
}
func Start(id int32, port string) {
connectToNode(port) //clienten's server og den er correct
file, _ := os.Open("replicamanager/portlist/listOfReplicaPorts.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
scanner.Scan()
po := scanner.Text()
// Her skal de 3 metoder ind. og 2 go rutiner
// Næste step. Når frontend modtager 5 forskellige svar fra fem replicas,
// skal der tages majority og sendes tilbage til clienten.
// svarne fra go rutinerne skal samles i en liste og så skal de compares på en eller anden måde.
}
bl := make(chan bool)
<-bl
}
func connectToNode(port string) {
s := &Server{}
lis, err := net.Listen("tcp", port)
if err != nil {
logger.InfoLogger.Printf(fmt.Sprintf("FATAL: Connection unable to establish. Failed to listen: %v", err))
}
grpcServer := grpc.NewServer()
protos.RegisterAuctionhouseServiceServer(grpcServer, s)
go func() {
if err := grpcServer.Serve(lis); err != nil {
logger.ErrorLogger.Fatalf("FATAL: Server connection failed: %s", err)
}
}()
bl := make(chan bool)
<-bl
}
func (s *Server) Bid(stream protos.AuctionhouseService_BidServer) error {
fin := make(chan bool)
go s.HandleNewBidForClient(fin, stream)
bl := make(chan error)
return <-bl
}
// TODO ... skal modtage fra client of forwarde ti replicas.
func (s *Server) HandleNewBidForClient(fin chan (bool), srv protos.AuctionhouseService_BidServer) {
for {
var bid, err = srv.Recv()
if err != nil {
logger.ErrorLogger.Println(fmt.Sprintf("FATAL: failed to recive bid from client: %s", err))
} else {
//check if client is subscribed
_, ok := s.auctioneer.Load(bid.ClientId)
if !ok {
s.auctioneer.Store(bid.ClientId, sub{streamBid: srv, finished: fin})
logger.InfoLogger.Printf("Storing new client %v, in server map", bid.ClientId)
}
//Handle new bid - is bid higher than the last highest bid?
if bid.Amount > currentHighestBidder.HighestBidAmount {
highBidder := HighestBidder{
HighestBidAmount: bid.Amount,
HighestBidderID: bid.ClientId,
streamBid: srv,
}
currentHighestBidder = highBidder
logger.InfoLogger.Printf("Storing new bid %d for client %d in server map", bid.Amount, bid.ClientId)
}
s.SendBidStatusToClient(srv, bid.ClientId, bid.Amount)
}
}
}
//TODO
func (s *Server) SendBidStatusToClient(stream protos.AuctionhouseService_BidServer, currentBidderID int32, currentBid int32) {
var status protos.Status
// Her skal den svarer clietn NÅR!!!!! den har modtaget majority af ackno fra replicas!
switch {
case currentHighestBidder.HighestBidderID == currentBidderID && currentHighestBidder.HighestBidAmount == currentBid:
status = protos.Status_NOW_HIGHEST_BIDDER
case currentHighestBidder.HighestBidderID != currentBidderID || currentHighestBidder.HighestBidAmount > currentBid:
status = protos.Status_TOO_LOW_BID
default:
status = protos.Status_EXCEPTION
}
bidStatus := &protos.StatusOfBid{
Status: status,
HighestBid: currentHighestBidder.HighestBidAmount,
}
stream.Send(bidStatus)
}
// When time has runned out : brodcast who the winner is
func (s *Server) Result(stream protos.AuctionhouseService_ResultServer) error {
er := make(chan error)
go s.receiveQueryForResultAndSendToClient(stream, er)
return <-er
}
// wait for a client to ask for the highest bidder and sends the result back
func (s *Server) receiveQueryForResultAndSendToClient(srv protos.AuctionhouseService_ResultServer, er_ chan error) {
for {
_, err := srv.Recv()
if err != nil {
logger.WarningLogger.Printf("FATAL: failed to recive QueryResult from client: %s", err)
} else {
// her skal den finde majority af replicasnes svar
queryResponse := &protos.ResponseToQuery{
AuctionStatusMessage: "",
HighestBid: currentHighestBidder.HighestBidAmount,
HighestBidderID: currentHighestBidder.HighestBidderID,
Item: "",
}
er := srv.Send(queryResponse)
if er != nil {
logger.ErrorLogger.Fatalf("FATAL: failed to send ResponseToQuery to client: %s", err)
}
logger.InfoLogger.Println("Query sent to client")
}
}
}
func Output(input string) {
fmt.Println(input)
}