Exemple #1
0
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
}
Exemple #3
0
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
}
Exemple #4
0
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")
}
Exemple #7
0
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
}
Exemple #10
0
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
}
Exemple #13
0
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
}