예제 #1
0
파일: bidder.py 프로젝트: NeilSoul/Auction
class Bidder(object):
	def __init__(self, bidder_params, logger):
		# INIT properties
		self.bidder_params = bidder_params
		self.peername = bidder_params['peer']
		self.silent = bidder_params['silent']
		self.streaming_url = bidder_params['url']
		self.buffer_folder = setting.BUFFER_DIR
		# discovery center
		self.discovery_center = Broadcaster(
			bidder_params['broadcast'], 
			setting.DIS_BID_PORT)
		# message center
		self.message_center = Message(
			setting.MSG_HOST, 
			setting.MSG_BID_PORT, 
			setting.MSG_AUC_PORT, 
			BidderProtocol(self))
		# transport center
		self.transport_center = transport.TransportServer(
			setting.TRP_HOST,
			setting.TRP_PORT,
			TransportProtocol(self))
		# player
		self.player = BidderPlayer(self)
		# log center
		self.logger = logger #self.logger = log.LogClient(peername, bidder_params['broadcast'])
		self.running = 0
		
	""" Bidder(receiver, player) Life Cycle """
	def run(self):
		print ''
		print '### Bidder', self.peername, '( kcapacity = ', self.bidder_params['kcapacity'],') running...'
		print ''
		self.running = 1
		self.prepare()
		self.player.play()
		self.discovery_center.run()
		self.message_center.run()
		self.transport_center.start()
		

	def join(self):
		self.transport_center.join()

	def close(self):
		self.discovery_center.close()
		self.message_center.close()
		self.transport_center.close()
		self.player.close()
		self.running = 0
		self.task_timeout_cond.acquire()
		self.task_timeout_cond.notify()
		self.task_timeout_cond.release()
		print ''
		print '### Bidder', self.peername, 'stopped'
		print ''

	def prepare(self):
		self.player.prepare2play()
		# the index of which trunk is ready to write into buffer  
		self.ready_index = 0
		# wait for auction : priority queue [segment number]
		self.auction_waiting_queue = PriorityQueue()
		for i in range(self.player.get_segment_number()):
			self.auction_waiting_queue.put(i)
		# wait for retrieve : dictionary { index: (rate,time) }
		self.retrieving = {}
		# retrieved : dictionary  { index:(rate,data) }
		self.retrieved = {}
		self.task_cond = threading.Condition()
		threading.Thread(target=self.task_loop, args=(1.0, )).start()
		# timeout protection
		self.task_timeout_cond = threading.Condition()
		threading.Thread(target=self.task_timeout, args=(setting.AUCTIONEER_DOWNLOAD_TIMEOUT,)).start()
		# core
		self.core = BidderCore(self, self.bidder_params)

	def buffer_size(self):
		buffer_in_player = self.player.get_buffer()
		buffer_in_auction = self.player.get_segment_duration() * (len(self.retrieved) + len(self.retrieving))
		return buffer_in_player + buffer_in_auction

	""" Bid Factory.
	bid : bid for auction.
	send task : send segment task for auction.
	"""
	def bid(self, ip, auction):
		bid_pack = self.core.bid2auction(auction)
		if bid_pack:
			# unpack
			auction_peer, auction_index, bid = bid_pack
			# logging
			#self.logger.log('B', [self.peername, auction_peer, auction_index, self.buffer_size(), bid])
			logcontent = 'auctioneer=%s, index=%d, buffer=%0.2f, bitrates=%s, prices=%s, gains=%s' % (auction_peer, int(auction_index), self.buffer_size(), str([ r/1024.0/1024.0 for r in bid[0]]), str(bid[1]), str(bid[2]))
			self.logger.slave_bid(logcontent)
			# response
			bid_info = ','.join([auction_index, str(bid)])
			self.message_center.sendto(ip, ':'.join(['BID', bid_info]))

	def send_task(self, ip, info):
		segment_allocated, rate = map(lambda a:int(a), info.split(','))
		self.core.update_previous(rate)
		while segment_allocated > 0 and not self.auction_waiting_queue.empty():
			index = self.auction_waiting_queue.get()
			task_url = self.player.get_segment_url(index, rate)
			f_rate = float(rate)/1024/1024  
			print '[B     sended] No.%d, rate=%0.2f(mbps)' % (index, f_rate)
			# send it to bidder
			self.retrieving[index] = (f_rate, time.time())
			self.message_center.sendto(ip, 'TASK:'+str(index)+','+task_url)
			segment_allocated = segment_allocated - 1

	""" Transport Factory """
	def receive_trunk(self, ip, index, data):
		print '[B   received] No.%s, size=%0.2f(mb), buffer=%0.2f(s)' % (index, float(len(data))/1024/128, self.buffer_size())
		# discard wild data
		if not index in self.retrieving: 
			return
		# retrieve thread safe
		self.task_cond.acquire()
		self.retrieved[index] = (self.retrieving[index][0], data)
		del self.retrieving[index]
		self.task_cond.notify()
		self.task_cond.release()
		

	def fail_trunk(self, ip, index):
		if not index in self.retrieving: #wild data
			return
		del self.retrieving[index]
		self.auction_waiting_queue.put(index)

	""" Task """
	def task_timeout(self, timeout):
		while self.running:
			now = time.time()
			for index in self.retrieving:#TODO thread safe
				if self.retrieving[index][1] - now > timeout:
					del self.retrieving[index]
					self.auction_waiting_queue.put(index)
			#time.sleep(timeout)
			self.task_timeout_cond.acquire()
			self.task_timeout_cond.wait(timeout)
			self.task_timeout_cond.release()

	def task_loop(self, timeout):
		while self.running:
			self.task_cond.acquire()
			while self.running and not self.ready_index in self.retrieved:
				self.task_cond.wait(timeout)
			if not self.running:
				break
			if self.ready_index in self.retrieved:
				self.player.segment_received(self.ready_index, self.retrieved[self.ready_index])
				del self.retrieved[self.ready_index]
				self.ready_index = self.ready_index + 1
			self.task_cond.release()
예제 #2
0
class Bidder(object):
    def __init__(self, bidder_params, logger):
        # INIT properties
        self.bidder_params = bidder_params
        self.peername = bidder_params['peer']
        self.silent = bidder_params['silent']
        self.streaming_url = bidder_params['url']
        self.buffer_folder = setting.BUFFER_DIR
        # discovery center
        self.discovery_center = Broadcaster(bidder_params['broadcast'],
                                            setting.DIS_BID_PORT)
        # message center
        self.message_center = Message(setting.MSG_HOST, setting.MSG_BID_PORT,
                                      setting.MSG_AUC_PORT,
                                      BidderProtocol(self))
        # transport center
        self.transport_center = transport.TransportServer(
            setting.TRP_HOST, setting.TRP_PORT, TransportProtocol(self))
        # player
        self.player = BidderPlayer(self)
        # log center
        self.logger = logger  #self.logger = log.LogClient(peername, bidder_params['broadcast'])
        self.running = 0

    """ Bidder(receiver, player) Life Cycle """

    def run(self):
        print ''
        print '### Bidder', self.peername, '( kcapacity = ', self.bidder_params[
            'kcapacity'], ') running...'
        print ''
        self.running = 1
        self.prepare()
        self.player.play()
        self.discovery_center.run()
        self.message_center.run()
        self.transport_center.start()

    def join(self):
        self.transport_center.join()

    def close(self):
        self.discovery_center.close()
        self.message_center.close()
        self.transport_center.close()
        self.player.close()
        self.running = 0
        self.task_timeout_cond.acquire()
        self.task_timeout_cond.notify()
        self.task_timeout_cond.release()
        print ''
        print '### Bidder', self.peername, 'stopped'
        print ''

    def prepare(self):
        self.player.prepare2play()
        # the index of which trunk is ready to write into buffer
        self.ready_index = 0
        # wait for auction : priority queue [segment number]
        self.auction_waiting_queue = PriorityQueue()
        for i in range(self.player.get_segment_number()):
            self.auction_waiting_queue.put(i)
        # wait for retrieve : dictionary { index: (rate,time) }
        self.retrieving = {}
        # retrieved : dictionary  { index:(rate,data) }
        self.retrieved = {}
        self.task_cond = threading.Condition()
        threading.Thread(target=self.task_loop, args=(1.0, )).start()
        # timeout protection
        self.task_timeout_cond = threading.Condition()
        threading.Thread(target=self.task_timeout,
                         args=(setting.AUCTIONEER_DOWNLOAD_TIMEOUT, )).start()
        # core
        self.core = BidderCore(self, self.bidder_params)

    def buffer_size(self):
        buffer_in_player = self.player.get_buffer()
        buffer_in_auction = self.player.get_segment_duration() * (
            len(self.retrieved) + len(self.retrieving))
        return buffer_in_player + buffer_in_auction

    """ Bid Factory.
	bid : bid for auction.
	send task : send segment task for auction.
	"""

    def bid(self, ip, auction):
        bid_pack = self.core.bid2auction(auction)
        if bid_pack:
            # unpack
            auction_peer, auction_index, bid = bid_pack
            # logging
            #self.logger.log('B', [self.peername, auction_peer, auction_index, self.buffer_size(), bid])
            logcontent = 'auctioneer=%s, index=%d, buffer=%0.2f, bitrates=%s, prices=%s, gains=%s' % (
                auction_peer, int(auction_index), self.buffer_size(),
                str([r / 1024.0 / 1024.0
                     for r in bid[0]]), str(bid[1]), str(bid[2]))
            self.logger.slave_bid(logcontent)
            # response
            bid_info = ','.join([auction_index, str(bid)])
            self.message_center.sendto(ip, ':'.join(['BID', bid_info]))

    def send_task(self, ip, info):
        segment_allocated, rate = map(lambda a: int(a), info.split(','))
        self.core.update_previous(rate)
        while segment_allocated > 0 and not self.auction_waiting_queue.empty():
            index = self.auction_waiting_queue.get()
            task_url = self.player.get_segment_url(index, rate)
            f_rate = float(rate) / 1024 / 1024
            print '[B     sended] No.%d, rate=%0.2f(mbps)' % (index, f_rate)
            # send it to bidder
            self.retrieving[index] = (f_rate, time.time())
            self.message_center.sendto(ip,
                                       'TASK:' + str(index) + ',' + task_url)
            segment_allocated = segment_allocated - 1

    """ Transport Factory """

    def receive_trunk(self, ip, index, data):
        print '[B   received] No.%s, size=%0.2f(mb), buffer=%0.2f(s)' % (
            index, float(len(data)) / 1024 / 128, self.buffer_size())
        # discard wild data
        if not index in self.retrieving:
            return
        # retrieve thread safe
        self.task_cond.acquire()
        self.retrieved[index] = (self.retrieving[index][0], data)
        del self.retrieving[index]
        self.task_cond.notify()
        self.task_cond.release()

    def fail_trunk(self, ip, index):
        if not index in self.retrieving:  #wild data
            return
        del self.retrieving[index]
        self.auction_waiting_queue.put(index)

    """ Task """

    def task_timeout(self, timeout):
        while self.running:
            now = time.time()
            for index in self.retrieving:  #TODO thread safe
                if self.retrieving[index][1] - now > timeout:
                    del self.retrieving[index]
                    self.auction_waiting_queue.put(index)
            #time.sleep(timeout)
            self.task_timeout_cond.acquire()
            self.task_timeout_cond.wait(timeout)
            self.task_timeout_cond.release()

    def task_loop(self, timeout):
        while self.running:
            self.task_cond.acquire()
            while self.running and not self.ready_index in self.retrieved:
                self.task_cond.wait(timeout)
            if not self.running:
                break
            if self.ready_index in self.retrieved:
                self.player.segment_received(self.ready_index,
                                             self.retrieved[self.ready_index])
                del self.retrieved[self.ready_index]
                self.ready_index = self.ready_index + 1
            self.task_cond.release()