func iNewLspServer(port int, params *LspParams) (*LspServer, error) { srv := new(LspServer) srv.nextId = 1 if params == nil { // Insert default parameters params = &LspParams{5, 2000} } srv.params = params hostport := fmt.Sprintf(":%v", port) addr, err := lspnet.ResolveUDPAddr("udp", hostport) if lsplog.CheckReport(1, err) { return nil, err } srv.udpConn, err = lspnet.ListenUDP("udp", addr) if lsplog.CheckReport(1, err) { return nil, err } srv.readBuf = NewBuf() // Need enough room to recycle close messages srv.appReadChan = make(LspMessageChan, 1) srv.appWriteChan = make(LspMessageChan) srv.netInChan = make(networkChan) srv.epochChan = make(chan int) srv.connById = make(map[uint16]*lspConn) srv.connByAddr = make(map[string]*lspConn) srv.closeReplyChan = make(chan error, 1) srv.closeAllReplyChan = make(chan error, 1) srv.writeReplyChan = make(chan error, 1) go srv.serverLoop() go srv.udpReader() go epochTrigger(srv.params.EpochMilliseconds, srv.epochChan, &srv.stopGlobalNetworkFlag) return srv, nil }
func NewTribserver(agencyid, master, ownstorage, myhostport string, prefer int) *Tribserver { lsplog.SetVerbose(3) //Connect to master lc, err := libconn.NewLibconn(agencyid, master, myhostport, prefer) if lsplog.CheckReport(1, err) { return nil } //Init libstore : Agency storage server ls, err := libstore.NewLibstore(agencyid, ownstorage, myhostport, libstore.NONE) if lsplog.CheckReport(1, err) { log.Printf("[%s:%s] Fail to start", agencyid, myhostport) return nil } //Init libairline : Airline storage server la, err := libairline.NewLibairline(lc, agencyid, myhostport) if lsplog.CheckReport(1, err) { log.Printf("[%s:%s] Fail to start", agencyid, myhostport) return nil } //lsplog.Vlogf(5, "Server active... %s", myhostport); log.Printf("[%s:%s] Start", agencyid, myhostport) return &Tribserver{ls, la, agencyid, myhostport} }
//Broadcast message to all replicas func (lp *Libpaxos) broadcast(PacketMsg *Msg) { if PacketMsg != nil { //lsplog.Vlogf(6, "[Libpaxos] Broadcast type: %d", PacketMsg.MsgType) p := Packet{} p.PacketFrom = lp.self p.PacketMsg = *PacketMsg var reply Reply for _, r := range lp.replicas { // if r == lp.self { // continue // } //lsplog.Vlogf(6, "[Libpaxos] Broadcast: %s", r) client, err := rpc.DialHTTP("tcp", r) if lsplog.CheckReport(6, err) { lsplog.Vlogf(6, "[Libpaxos] Broadcast to %s failed", r) //client.Close() continue } err = client.Call("Libpaxos.ReceiveMessage", p, &reply) if lsplog.CheckReport(1, err) { lsplog.Vlogf(6, "[Libpaxos] Broadcast call to %s failed", r) } client.Close() } } }
// Write message to UDP connection. Address already registered with connection func (cli *LspClient) udpWrite(msg *LspMessage) { b := msg.genPacket() _, err := cli.udpConn.Write(b) if lsplog.CheckReport(6, err) { cli.Vlogf(6, "Write failed\n") } }
// Shutting down network communications func (cli *LspClient) stopNetwork() { cli.lspConn.stopNetworkFlag = true err := cli.udpConn.Close() if lsplog.CheckReport(4, err) { lsplog.Vlogf(6, "Client Continuing\n") } }
func (la *Libairline) CreateFlight(flight airlineproto.FlightInfo) error { log.Printf("[%s:%s] Start to add flight: %s\n", la.agencyid, la.myhostport, flight.ID) conn, err := la.lib_conn.GetServer(tribproto.GetAirlineFromFlightId(flight.ID)) if err != nil { log.Printf("[%s:%s] Fail to add flight: %s\n", la.agencyid, la.myhostport, flight.ID) return lsplog.MakeErr("Airline doesn't exist") } args := &airlineproto.PutArgs{flight.ID, flight} var reply airlineproto.PutReply err = conn.Call("AirlineRPC.CreateFlight", args, &reply) if lsplog.CheckReport(2, err) { log.Printf("[%s:%s] Fail to add flight: %s\n", la.agencyid, la.myhostport, flight.ID) return lsplog.MakeErr("Flight already exist") } if reply.Status != airlineproto.OK { log.Printf("[%s:%s] Fail to add flight: %s\n", la.agencyid, la.myhostport, flight.ID) return lsplog.MakeErr("Flight already exist") } log.Printf("[%s:%s] Succeed to add flight: %s\n", la.agencyid, la.myhostport, flight.ID) return nil }
func (tl *TranLayer) BookingFlights(orderList []tranlayerproto.Order) error { // find server for each airline company tranOrderList := make([]*tranOrder, len(orderList)) for i, order := range orderList { conn, pptID, err := tl.lib_conn.GetServerWithAddress(order.AirlineID) if lsplog.CheckReport(2, err) { return err } tranOrderList[i] = &tranOrder{order.FlightID, pptID, order.Amount, conn} } // get unique transaction id tranID := fmt.Sprintf("%s:%d", tl.myhostport, time.Now().UnixNano()) lsplog.Vlogf(5, "Begin transaction:"+tranID) // send request to store handler req := &reqContent{INIT_TRANS, tranID, tranOrderList} replyc := make(chan interface{}) tl.reqChan <- &Request{req, replyc} // wait for response status := (<-replyc).(bool) lsplog.Vlogf(5, "End of transaction:"+tranID) if status { return nil } return lsplog.MakeErr("Transaction Failed") }
// Shut down all network activity func (srv *LspServer) stopGlobalNetwork() { srv.stopGlobalNetworkFlag = true err := srv.udpConn.Close() if lsplog.CheckReport(4, err) { lsplog.Vlogf(6, "Server Continuing\n") } }
// Write message to UDP connection. Address specified by con func (srv *LspServer) udpWrite(con *lspConn, msg *LspMessage) { b := msg.genPacket() _, err := srv.udpConn.WriteToUDP(b, con.addr) if lsplog.CheckReport(6, err) { srv.Vlogf(6, "Write failed\n") } }
func (ts *Tribserver) GetBookings(args *tribproto.GetBookingsArgs, reply *tribproto.GetBookingsReply) error { lsplog.Vlogf(5, "Get bookings: "+args.Userid) flightids, err := ts.lib_store.GetList(getUserBookingsKey(args.Userid), ts.agencyid) if lsplog.CheckReport(3, err) { reply.Status = tribproto.ENOSUCHUSER return nil } flightsInfo, ferr := ts.doGetFlightsFromIds(flightids) if lsplog.CheckReport(3, ferr) { return ferr } reply.Flights = flightsInfo reply.Status = tribproto.OK return nil }
func (ts *Tribserver) ViewFlights(args *tribproto.ViewFlightsArgs, reply *tribproto.ViewFlightsReply) error { lsplog.Vlogf(5, "Get flights:"+args.From+" to:"+args.To+" date:"+args.DepartureDate) flightids, err := ts.lib_airline.GetAllFlights(args.From, args.To, args.DepartureDate) if lsplog.CheckReport(3, err) { return lsplog.MakeErr("Error fetching flight ids") } flightsInfo, ferr := ts.doGetFlightsFromIds(flightids) if lsplog.CheckReport(3, ferr) { return ferr } reply.Flights = flightsInfo reply.Status = tribproto.OK return nil }
// Goroutine that reads messages from UDP connection and writes to message channel func (cli *LspClient) udpReader() { udpConn := cli.udpConn mc := cli.netInChan var buffer [1500]byte for !cli.lspConn.stopNetworkFlag { n, _, err := udpConn.ReadFromUDP(buffer[0:]) if lsplog.CheckReport(1, err) { cli.Vlogf(6, "Client continuing\n") continue } m, merr := extractMessage(buffer[0:n]) if lsplog.CheckReport(1, merr) { cli.Vlogf(6, "Client continuing\n") continue } mc <- m } }
func (ts *Tribserver) CreateUser(args *tribproto.CreateUserArgs, reply *tribproto.CreateUserReply) error { //Check for existing user if ts.doesUserExist(args.Userid) { reply.Status = tribproto.EEXISTS return nil } // Create empty bookings entry for user cerr := ts.lib_store.Put(getNewUserKey(args.Userid), "new_user", ts.agencyid) perr := ts.lib_store.Put(getUserBookingsKey(args.Userid), "", ts.agencyid) if lsplog.CheckReport(3, cerr) || lsplog.CheckReport(3, perr) { return lsplog.MakeErr("Error creating user") } lsplog.Vlogf(5, "Created user:"+args.Userid) reply.Status = tribproto.OK return nil }
func (la *Libairline) GetFlight(flightid string) (airlineproto.FlightInfo, error) { conn, err := la.lib_conn.GetServer(tribproto.GetAirlineFromFlightId(flightid)) if lsplog.CheckReport(2, err) { return airlineproto.FlightInfo{}, err } args := &airlineproto.GetArgs{flightid, false, ""} var reply airlineproto.GetReply err = conn.Call("AirlineRPC.GetFlight", args, &reply) if lsplog.CheckReport(2, err) { return airlineproto.FlightInfo{}, err } if reply.Status != airlineproto.OK { return airlineproto.FlightInfo{}, lsplog.MakeErr("Fetch flight failed") } return reply.FlightInfo, nil }
// Goroutine that reads messages from UDP connection and writes to message channel func (srv *LspServer) udpReader() { udpConn := srv.udpConn netc := srv.netInChan var buffer [1500]byte for !srv.stopGlobalNetworkFlag { n, addr, err := udpConn.ReadFromUDP(buffer[0:]) if lsplog.CheckReport(1, err) { srv.Vlogf(5, "Server continuing\n") continue } m, merr := extractMessage(buffer[0:n]) if lsplog.CheckReport(1, merr) { srv.Vlogf(6, "Server continuing\n") continue } srv.Vlogf(5, "Received message %s\n", m) d := &networkData{m, addr} netc <- d } }
func iNewLspClient(hostport string, params *LspParams) (*LspClient, error) { cli := new(LspClient) if params == nil { // Insert default parameters params = &LspParams{5, 2000} } cli.params = params addr, err := lspnet.ResolveUDPAddr("udp", hostport) if lsplog.CheckReport(1, err) { return nil, err } cli.lspConn = newConn(addr, 0, 0) // Client's first received message will be data message. cli.lspConn.nextRecvSeqNum = NextSeqNum(0) cli.udpConn, err = lspnet.DialUDP("udp", nil, addr) if lsplog.CheckReport(1, err) { return nil, err } // Need enough room to recycle close messages at end cli.appReadChan = make(LspMessageChan, 2) cli.readBuf = NewBuf() cli.appWriteChan = make(LspMessageChan, 1) cli.netInChan = make(LspMessageChan, 1) cli.epochChan = make(chan int) cli.closeReplyChan = make(chan error, 2) cli.writeReplyChan = make(chan error, 2) go cli.clientLoop() go cli.udpReader() go epochTrigger(cli.params.EpochMilliseconds, cli.epochChan, &cli.lspConn.stopNetworkFlag) // Send connection request to server nm := GenConnectMessage() cli.udpWrite(nm) cli.lspConn.pendingMsg = nm cli.lspConn.nextSendSeqNum = NextSeqNum(0) cm := <-cli.appReadChan if cm.Type == MsgCONNECT { return cli, nil } return nil, lsplog.MakeErr("Connection failed") }
func NewLibairline(lc *libconn.Libconn, agencyid, myhostport string) (*Libairline, error) { la := &Libairline{} la.lib_conn = lc la.agencyid = agencyid la.myhostport = myhostport trnlayer, err := tranlayer.NewTranLayer(lc, agencyid, myhostport) if lsplog.CheckReport(2, err) { return nil, err } // Declare existense err = lc.DeclareExistence() if lsplog.CheckReport(2, err) { return nil, err } la.lib_tranlayer = trnlayer return la, nil }
func (ts *Tribserver) doGetFlightsFromIds(flightids []string) ([]airlineproto.FlightInfo, error) { flightsInfo := make([]airlineproto.FlightInfo, len(flightids)) for i, fid := range flightids { f, err := ts.lib_airline.GetFlight(fid) lsplog.Vlogf(6, "Flight id "+fid) if lsplog.CheckReport(3, err) { return nil, lsplog.MakeErr("Error fetching flight from flight id") } flightsInfo[i] = f } return flightsInfo, nil }
func (lc *Libconn) appendList(key, value string) error { args := &storageproto.PutArgs{key, value} var reply storageproto.PutReply err := lc.conn.Call("StorageRPC.AppendToList", args, &reply) if lsplog.CheckReport(2, err) { //log.Printf("[%s:%s] Airline already declared\n", lc.entityid, lc.myhostport) return lsplog.MakeErr("Declare existense failed") } if reply.Status != storageproto.OK { //log.Printf("[%s:%s] Airline already declared\n", lc.entityid, lc.myhostport) return lsplog.MakeErr("Declare Existense Failed") } return nil }
func (la *Libairline) MakeBooking(flightids []string, isRemove bool) error { //TODO: Handle remove orderQuantity := 1 if isRemove { orderQuantity = -1 } orderGrpMap := make(map[string]*bufi.Buf) for _, v := range flightids { airlineId := tribproto.GetAirlineFromFlightId(v) orderList, exist := orderGrpMap[airlineId] if exist == false { orderList = bufi.NewBuf() } orderList.Insert(v) orderGrpMap[airlineId] = orderList } orders := make([]tranlayerproto.Order, len(orderGrpMap)) i := 0 for airlineId, orderList := range orderGrpMap { flightIds := "" for !orderList.Empty() { flightId := orderList.Remove().(string) if flightIds == "" { flightIds = flightId } else { flightIds = fmt.Sprintf("%s:%s", flightIds, flightId) } } order := tranlayerproto.Order{airlineId, flightIds, orderQuantity} orders[i] = order i++ } err := la.lib_tranlayer.BookingFlights(orders) if lsplog.CheckReport(2, err) { return err } return nil }
//TODO: Cache connections func NewLibconn(entityid, master, myhostport string, prefer int) (*Libconn, error) { lc := &Libconn{} lc.connLock = new(sync.Mutex) lc.connMap = make(map[int]*rpc.Client) lc.entityid = entityid lc.master = master lc.myhostport = myhostport lc.prefer = prefer //Connect to master node cli, err := rpc.DialHTTP("tcp", master) if lsplog.CheckReport(2, err) { return nil, err } lc.conn = cli return lc, nil }
func NewAirlineServer(airlineID, myhostport, masterStorage, ownStorage string, replicas []string, pos int) (*AirlineServer, *libpaxos.Libpaxos, error) { lsplog.SetVerbose(4) as := &AirlineServer{} as.cmdNO = 0 as.reqChan = make(chan *Request) as.airlineID = airlineID as.myhostport = myhostport as.logBuf = make(map[string](*bufi.Buf)) as.flightBuf = make(map[string](*airlineproto.FlightInfo)) as.flightQueryBuf = make(map[string](string)) as.lockBuf = make(map[string](bool)) as.oldLog = make(map[string]int) as.oldReplycMap = make(map[int](chan interface{})) q := len(replicas)/2 + len(replicas)%2 as.lp = libpaxos.NewLibpaxos(myhostport, replicas, q, pos, as) lc, err := libconn.NewLibconn(airlineID, masterStorage, myhostport, 0) if lsplog.CheckReport(2, err) { return nil, nil, err } as.lib_conn = lc // // // Create RPC connection to own storage server // conn2, err := rpc.DialHTTP("tcp", ownStorage) // if err != nil { // return nil, err // } // as.ownStorage = conn2 // // Declare existense lc.PublishAirline() lc.DeclareExistence() go as.storeHandler() log.Printf("[%s:%s] Start", airlineID, myhostport) return as, as.lp, nil }
func (la *Libairline) GetAllFlights(from, to, dep string) ([]string, error) { log.Printf("[%s:%s] Start to get flights from %s to %s, on %s\n", la.agencyid, la.myhostport, from, to, dep) conns, err := la.lib_conn.GetServers() if err != nil { log.Printf("[%s:%s] Fail to get flights from %s to %s, on %s\n", la.agencyid, la.myhostport, from, to, dep) return nil, err } flightMap := make(map[string]bool) for _, conn := range conns { args := &airlineproto.GetAllArgs{from, to, dep} var reply airlineproto.GetAllReply err := conn.Call("AirlineRPC.GetAllFlightIDs", args, &reply) if lsplog.CheckReport(2, err) { log.Printf("[%s:%s] Fail to get flights from %s to %s, on %s\n", la.agencyid, la.myhostport, from, to, dep) return nil, err } if reply.Status != airlineproto.OK { log.Printf("[%s:%s] Fail to get flights from %s to %s, on %s\n", la.agencyid, la.myhostport, from, to, dep) return nil, lsplog.MakeErr("Fetch all flights failed") } for _, flight := range reply.FlightIDs { flightMap[flight] = true } } flights := make([]string, len(flightMap)) i := 0 for flight, _ := range flightMap { flights[i] = flight i++ } log.Printf("[%s:%s] Succeed to get flights from %s to %s, on %s\n", la.agencyid, la.myhostport, from, to, dep) return flights, nil }
func (ts *Tribserver) doBookingTransaction(isRemove bool, args *tribproto.BookingArgs, reply *tribproto.BookingReply) error { if !ts.doesUserExist(args.Userid) { reply.Status = tribproto.ENOSUCHUSER return nil } _, ferr := ts.doGetFlightsFromIds(args.FlightIds) if lsplog.CheckReport(3, ferr) { reply.Status = tribproto.EBOOKINGFAILED return nil } // Do not attempt to decrement count if duplicate booking flights, err := ts.lib_store.GetList(getUserBookingsKey(args.Userid), ts.agencyid) if lsplog.CheckReport(3, err) { reply.Status = tribproto.EBOOKINGFAILED return nil } fmt.Println("tribimpl@", flights) exist := false for _, fid1 := range args.FlightIds { for _, fid2 := range flights { if fid1 == fid2 { exist = true } } } if !isRemove { if exist == true { reply.Status = tribproto.EEXISTS return nil } } else { if exist == false { reply.Status = tribproto.ENOTBOOKED return nil } } err = ts.lib_airline.MakeBooking(args.FlightIds, isRemove) if err != nil { reply.Status = tribproto.EBOOKINGFAILED return nil } //If successful add to user bookings list for _, fid := range args.FlightIds { var err error if !isRemove { err = ts.lib_store.AppendToList(getUserBookingsKey(args.Userid), fid, ts.agencyid) } else { err = ts.lib_store.RemoveFromList(getUserBookingsKey(args.Userid), fid, ts.agencyid) } if lsplog.CheckReport(3, err) { reply.Status = tribproto.EBOOKINGFAILED return err } } reply.Status = tribproto.OK return nil }