func (lc *Libconn) GetServerWithAddress(entityId string) (*rpc.Client, string, error) { // Get entity info args := &storageproto.GetArgs{entityId, false, ""} var reply storageproto.GetListReply err := lc.conn.Call("StorageRPC.GetList", args, &reply) if err != nil { log.Printf("[%s:%s] Cannot connect to master storage\n", lc.entityid, lc.myhostport) return nil, "", lsplog.MakeErr("Connect master storage failed") } if reply.Status != storageproto.OK { log.Printf("[%s:%s] Cannot find address for: %s\n", lc.entityid, lc.myhostport, entityId) return nil, "", lsplog.MakeErr("Get agency info failed") } if len(reply.Value) == 0 { return nil, "", lsplog.MakeErr("GetServer: Empty list from master for airline:" + entityId) } // Create RPC connection to airline server pos := 0 if lc.prefer == 0 { pos = int(time.Now().UnixNano()) % len(reply.Value) } else { pos = lc.prefer % len(reply.Value) } server := reply.Value[pos] cli, err := rpc.DialHTTP("tcp", server) if err != nil { log.Printf("[%s:%s] Cannot connect to: %s\n", lc.entityid, lc.myhostport, entityId) return nil, "", err } return cli, server, nil }
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 (lc *Libconn) GetServers() ([]*rpc.Client, error) { // Get airline info args := &storageproto.GetArgs{storageproto.ALL_AIRLINE, false, ""} var reply storageproto.GetListReply err := lc.conn.Call("StorageRPC.GetList", args, &reply) if err != nil { log.Printf("[%s:%s] Cannot connect to master storage\n", lc.entityid, lc.myhostport) return nil, lsplog.MakeErr("Connect master storage failed") } if reply.Status != storageproto.OK { log.Printf("[%s:%s] Cannot find airline list\n", lc.entityid, lc.myhostport) return nil, lsplog.MakeErr("Get server list failed") } // Create RPC connection to airline servers servers := reply.Value conns := make([]*rpc.Client, len(servers)) i := 0 for _, server := range servers { conn, err := lc.GetServer(server) if err == nil { conns[i] = conn i++ } } return conns, 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 (ts *Tribserver) AddFlight(args *tribproto.AddFlightArgs, reply *tribproto.AddFlightReply) error { err := ts.lib_airline.CreateFlight(args.Flight) if err == lsplog.MakeErr("Airline doesn't exist") { reply.Status = tribproto.ENOAIRLINE return nil } if err == lsplog.MakeErr("Flight already exist") { reply.Status = tribproto.EEXISTS return nil } reply.Status = tribproto.OK 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") }
func (lc *Libconn) GetServerAt(hostport string) (*rpc.Client, error) { //TODO: cli, err := rpc.DialHTTP("tcp", hostport) if err != nil { return nil, lsplog.MakeErr("Connect airline failed") } return cli, nil }
// iGetList // parameters: // - key: the key for entry // return: // - value list related to the key // - error // function: // - get cached value or ask storage server // - cache new value func (ls *Libstore) iGetList(key, clusterid string) ([]string, error) { // Check cache first wantlease := false if ls.myhostport != "" { // register query if ls.flags == ALWAYS_LEASE { wantlease = true } else { replyc := make(chan interface{}) req := &CacheReq{NEW_QUERY, 0, key, "", replyc} ls.cacheReqC <- req wantlease = (<-replyc).(bool) } // check cache replyc := make(chan interface{}) req := &CacheReq{FETCH_CACHE_LIST, 0, key, "", replyc} ls.cacheReqC <- req cacheValue := <-replyc if cacheValue != nil { return cacheValue.([]string), nil } } // Query storage server args := &storageproto.GetArgs{key, wantlease, ls.myhostport} var reply storageproto.GetListReply cli, err := ls.getServer(key) if err != nil { return nil, err } err = cli.Call("StorageRPC.GetList", args, &reply) if err != nil { return nil, err } if reply.Status != storageproto.OK { return nil, lsplog.MakeErr("GetList failed: Storage error") } // Cache new value if wantlease { if reply.Lease.Granted { time := reply.Lease.ValidSeconds replyc := make(chan interface{}) req := &CacheReq{CREATE_CACHE, time, key, reply.Value, replyc} ls.cacheReqC <- req <-replyc } } return reply.Value, 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 (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 }
// iRemoveFromList // parameters: // - key: the key for item // - removeitem: the item to remove // return: // - error // function: // - send key and removeitem to storage server func (ls *Libstore) iRemoveFromList(key, removeitem, clusterid string) error { // Remove list value args := &storageproto.PutArgs{key, removeitem} var reply storageproto.PutReply cli, err := ls.getServer(key) if err != nil { return err } err = cli.Call("StorageRPC.RemoveFromList", args, &reply) if err != nil { return err } if reply.Status != storageproto.OK { return lsplog.MakeErr("RemoveFromList failed: Storage error") } return nil }
// iPut // parameters: // - key: the key for entry // - value: value to store // return: // - error // function: // - send key and value to storage server func (ls *Libstore) iPut(key, value, clusterid string) error { // Put value args := &storageproto.PutArgs{key, value} var reply storageproto.PutReply cli, err := ls.getServer(key) if err != nil { return err } err = cli.Call("StorageRPC.Put", args, &reply) if err != nil { return err } if reply.Status != storageproto.OK { return lsplog.MakeErr("Put failed: Storage error") } return nil }
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 }
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 (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 }
// iNewLibstore // parameters: // - server: master sever host port // - myhostport: local port to handle cache rpc // - flags: ALWAYS->always ask lease // return: // - pointer to new libstore // function: // - initialize libstore // - create connection to the master server // - get storage servers' infomation // - set up cachHandler, garbage collector timer and cache expiration timer func iNewLibstore(agencyid, server, myhostport string, flags int) (*Libstore, error) { // Initialize new libstore ls := &Libstore{} ls.flags = flags ls.myhostport = myhostport ls.cacheReqC = make(chan *CacheReq) // Create RPC connection to storage server cli, err := rpc.DialHTTP("tcp", server) if err != nil { return nil, err } // Get list of storage servers from master storage server args := storageproto.GetServersArgs{} var reply storageproto.RegisterReply // Try to connect to storage server for at most 5 times try := 5 sleepTime := 2000 for i := 0; ; i++ { err = cli.Call("StorageRPC.GetServers", args, &reply) if err == nil && reply.Ready { ls.cacheLock = new(sync.RWMutex) ls.cacheMap = make(map[string]*CacheEntry) ls.connLock = new(sync.Mutex) ls.connMap = make(map[int]*rpc.Client) ls.nodelist = reply.Servers crpc := cacherpc.NewCacheRPC(ls) rpc.Register(crpc) for i := 1; i < len(ls.nodelist); i++ { if server == ls.nodelist[i].HostPort { ls.connLock.Lock() ls.connMap[i] = cli ls.connLock.Unlock() break } } // succeeded go ls.cacheHandler() go ls.cacheTimer(2*storageproto.LEASE_SECONDS, GARBAGE_COLLECT) go ls.cacheTimer(storageproto.QUERY_CACHE_SECONDS, QUERY_COLLECT) return ls, nil } // failed if i == try-1 { if err != nil { return nil, err } return nil, lsplog.MakeErr("Storage system not ready") } time.Sleep(time.Duration(sleepTime) * time.Millisecond) } // Impossible to come here return ls, nil }