Exemple #1
0
func (c *client) waitOnline(msg *define.Msg) (err error) {
	// Push the online msg
	glog.Info("Get a online msg")
	// Check the msg time
	if msg.Expired > 0 {
		if time.Now().UTC().Unix() > msg.Expired {
			// cancel send the msg
			glog.Info("Out of time")
			return
		}
	}
	// Add the msg into cache
	if msg == nil {
		err = errors.New("onlines has been close")
		return
	}
	if len(c.onlineCache) > Conf.MaxCacheMsg && Conf.MaxCacheMsg != 0 {
		err = fmt.Errorf("Online msg is out of range:%v", len(c.onlineCache))
		return
	}
	mid := c.getOnlineMsgId()
	if mid == -1 {
		return
	}
	msg.Msg_id = mid
	msg.Typ = define.ONLINE
	c.onlineCache[msg.Msg_id] = msg
	err = c.pushMsg(msg)
	c.counter++
	return
}
Exemple #2
0
func (c *Comet_RPC) WriteMsg(msg *define.Msg, r *myrpc.Reply) (err error) {
	msg.Dup = 0
	// Fix the Expired
	if msg.Expired > 0 {
		msg.Expired = time.Now().UTC().Add(time.Duration(msg.Expired)).Unix()
	}
	// Check the user whether online.
	b, addr, err := redis.IsExist(msg.To_id)
	if !b {
		if err != nil {
			glog.Error(err)
		}
		// User is offline.
		err = store.Manager.InsertOfflineMsg(msg, Conf.RPC_addr, Conf.Etcd_addr)
		if err != nil {
			glog.Error(err)
		} else {
			// nil error.
			r.IsOk = true
		}
		return err
	}
	// User is online.
	if addr == Conf.RPC_addr {
		// Call local comet.
		return c.WriteOnlineMsg(msg, r)
	} else {
		// RPC.
		c, err := rpc.DialHTTP("tcp", addr)
		if err != nil {
			return err
		}
		reply := new(myrpc.Reply)
		if err = c.Call("Comet_RPC.WriteOnlineMsg", msg, reply); err != nil {
			return err
		}
		r.IsRe = reply.IsRe
		r.IsOk = reply.IsOk
		return nil
	}
}
Exemple #3
0
func (*Comet_RPC) WriteOnlineMsg(msg *define.Msg, r *myrpc.Reply) (err error) {
	defer func() {
		if err == nil {
			r.IsOk = true
		} else {
			glog.Error(err)
		}
	}()
	glog.Info("Get a Write Online msg RPC")

	c := Users.Get(msg.To_id)
	if c == nil {
		msg.Typ = define.OFFLINE
		// Get the offline msg id
		err = store.Manager.InsertOfflineMsg(msg, Conf.RPC_addr, Conf.Etcd_addr)
		return
	}

	c.lock.Lock()
	if len(c.onlines) == Conf.MaxCacheMsg {
		c.lock.Unlock()
		msg.Typ = define.OFFLINE
		err = store.Manager.InsertOfflineMsg(msg, Conf.RPC_addr, Conf.Etcd_addr)
		return
	} else {
		c.lock.Unlock()
	}
	c.lock.Lock()
	if c.isStop {
		c.lock.Unlock()
		msg.Typ = define.OFFLINE
		err = store.Manager.InsertOfflineMsg(msg, Conf.RPC_addr, Conf.Etcd_addr)
	} else {
		msg.Typ = define.ONLINE
		c.onlines <- msg
		c.lock.Unlock()
	}
	return
}
Exemple #4
0
func (c *client) waitOffline(msg *define.Msg) (err error) {
	// Check the msg time
	if msg.Expired > 0 {
		if time.Now().UTC().Unix() > msg.Expired {
			// cancel send the msg
			glog.Info("Out of time.")
			// TODO Del the offline msg
			store.Manager.DelOfflineMsg(msg.Id)
			return
		}
	}
	msg.Msg_id = c.getOnlineMsgId()
	if msg.Msg_id == -1 {
		return
	}
	c.offline_map[msg.Msg_id] = msg.Id
	// Push the offline msg
	glog.Info("Get a offline msg")
	// Set the msg id
	err = c.pushOfflineMsg(msg)
	c.counter++
	return
}
Exemple #5
0
func writeOfflineMsg(msg *define.Msg) error {
	msg.Typ = define.OFFLINE
	return store.Manager.InsertOfflineMsg(msg, Conf.Listen_addr, Conf.Etcd_addr)
}
Exemple #6
0
// Push the msg and response the heart beat
func (c *client) listen_loop() (e error) {
	defer func() {
		err := redis.Logout(c.id, Conf.RPC_addr)
		if err != nil {
			err = redis.Logout(c.id, Conf.RPC_addr)
			if err != nil {
				glog.Errorf("Redis conn error:%v", err)
			}
			Users.Del(c.id)
			if c.isSendClose {
				c.closeChan <- 0
			}
		}
	}()
	var (
		err     error
		msg     *define.Msg
		pAndErr *packAndErr

		noticeFin = make(chan byte, 2)
		// wg        = new(sync.WaitGroup)

		findEndChan <-chan byte
	)

	// Start the write queue
	go c.queue.writeLoop()

	c.offlines, findEndChan = store.Manager.GetOfflineMsg(c.id, noticeFin)
	c.readChan = c.queue.ReadPackInLoop(noticeFin)

	// Start push
loop:
	for {
		if c.counter < math.MaxUint16 {
			select {
			case <-findEndChan:
				if err = c.offlineEnd(); err != nil {
					glog.Error(err)
					break loop
				}
			case msg := <-c.offlines:
				if err = c.waitOffline(msg); err != nil {
					glog.Error(err)
					break loop
				}
			case msg = <-c.onlines:
				if err = c.waitOnline(msg); err != nil {
					glog.Error(err)
					break loop
				}
			case pAndErr = <-c.readChan:
				if err = c.waitPack(pAndErr); err != nil {
					glog.Error("Get a connection error , will break(%v)", err)
					break loop
				}
			case <-c.closeChan:
				c.waitQuit()
				break loop
			}
		} else {
			select {
			case <-findEndChan:
				if err = c.offlineEnd(); err != nil {
					glog.Error(err)
					break loop
				}
			case pAndErr = <-c.readChan:
				if err = c.waitPack(pAndErr); err != nil {
					glog.Error(err)
					break loop
				}
			case <-c.closeChan:
				c.waitQuit()
				break loop
			}
		}

	}

	c.lock.Lock()
	c.isStop = true
	c.lock.Unlock()
	// Wrte the onlines msg to the db
	// Free resources
	// Close channels
	for i := 0; i < 2; i++ {
		noticeFin <- 1
	}
	close(noticeFin)
	// Write the onlines msg to the db
	for _, v := range c.onlineCache {
		// Add the offline msg id
		v.Typ = define.OFFLINE
		store.Manager.InsertOfflineMsg(v, Conf.RPC_addr, Conf.Etcd_addr)
	}
	// Flush the channel.
	for len(c.onlines) > 0 {
		msg := <-c.onlines
		msg.Typ = define.OFFLINE
		store.Manager.InsertOfflineMsg(msg, Conf.RPC_addr, Conf.Etcd_addr)
	}
	glog.Info("Cleaned the online msgs channel.")
	// Close the online msg channel
	close(c.onlines)
	close(c.closeChan)
	glog.Info("Groutine will esc.")
	return
}