# -*- coding: utf-8 -*-
#
#
# $Id: ussp.py,v 1.4 2004/11/15 07:00:13 xyb Exp $

"""Open Unified Storage System Protocol

Stability: None

@author: U{HD<mailto:hdcola@gmail.com>}

@see: Open Unified Storage System Protocol规范
"""
from compass.uss.protocols import byteprotocol
from compass.uss.message import usspmsg
from twisted.internet import reactor

class USSProtocol(byteprotocol.ByteMessageProtocol):
    """缺省USS协议实现"""
    def MessageReceived(self,packet):
        """接收到一条消息，对该消息进行处理"""
        message = usspmsg.USSPMessage()
        message.loadMessage(packet)
        # print message
        self.MessageProcess(message)

    def MessageProcess(self, message):
        """调用指定的方法来处理收到的消息"""
        method = getattr(self , "on_ussp_%s" % message.msgname, None)
        return method(message)

class USSClientQueueProtocol(USSProtocol):
    """使用滑动窗口队列的USS协议客户端实现"""

    def MessageReceived(self,packet):
        """接收到一条消息，确定该消息是否是已发送出的消息，
        如果是，从发送消息队列中清除该消息。然后按正常的流程执行下去。
        """
        message = usspmsg.USSPMessage()
        message.loadMessage(packet)
        # print message
        # 将发出的消息从队列中清楚
        self.factory.sendMsg.remove(message.head.sequence)
        self.MessageProcess(message)

    def connectionMade(self):
        """连接成功了，就可以启动发送线程了"""
        reactor.callInThread(self.sendQueueMesg)

    def sendDataToQueue(self, message):
        """将消息加入待发送队列"""
        if(not self.factory.sendQueue.full()):
            self.factory.sendQueue.put(message)
        else:
            self.call = reactor.callLater(0, self.sendDataToQueue, message)

    def sendQueueMesg(self):
        """将队列中的消息发送出去"""
        if (len(self.factory.sendMsg) < self.factory.WINMAX):
            while (not self.factory.sendQueue.empty()):
                message = self.factory.sendQueue.get()
                # 发送前设置消息的顺序号
                message.head.sequence = self.factory.sequence
                self.sendData(message.packed())
                # 将已经发送的消息放入已经发送的清单中
                self.factory.sendMsg.append(self.factory.sequence)
                self.factory.sequence += 1
        self.call = reactor.callLater(0, self.sendQueueMesg)
