72 lines
2.8 KiB
Python
72 lines
2.8 KiB
Python
|
"""
|
||
|
src/network/uploadthread.py
|
||
|
"""
|
||
|
# pylint: disable=unsubscriptable-object
|
||
|
import threading
|
||
|
import time
|
||
|
|
||
|
import helper_random
|
||
|
import protocol
|
||
|
from debug import logger
|
||
|
from helper_threading import StoppableThread
|
||
|
from inventory import Inventory
|
||
|
from network.connectionpool import BMConnectionPool
|
||
|
from network.dandelion import Dandelion
|
||
|
from randomtrackingdict import RandomTrackingDict
|
||
|
|
||
|
|
||
|
class UploadThread(threading.Thread, StoppableThread):
|
||
|
"""This is a thread that uploads the objects that the peers requested from me """
|
||
|
maxBufSize = 2097152 # 2MB
|
||
|
|
||
|
def __init__(self):
|
||
|
threading.Thread.__init__(self, name="Uploader")
|
||
|
self.initStop()
|
||
|
self.name = "Uploader"
|
||
|
logger.info("init upload thread")
|
||
|
|
||
|
def run(self):
|
||
|
while not self._stopped:
|
||
|
uploaded = 0
|
||
|
# Choose downloading peers randomly
|
||
|
connections = [x for x in BMConnectionPool().inboundConnections.values() +
|
||
|
BMConnectionPool().outboundConnections.values() if x.fullyEstablished]
|
||
|
helper_random.randomshuffle(connections)
|
||
|
for i in connections:
|
||
|
now = time.time()
|
||
|
# avoid unnecessary delay
|
||
|
if i.skipUntil >= now:
|
||
|
continue
|
||
|
if len(i.write_buf) > UploadThread.maxBufSize:
|
||
|
continue
|
||
|
try:
|
||
|
request = i.pendingUpload.randomKeys(RandomTrackingDict.maxPending)
|
||
|
except KeyError:
|
||
|
continue
|
||
|
payload = bytearray()
|
||
|
chunk_count = 0
|
||
|
for chunk in request:
|
||
|
del i.pendingUpload[chunk]
|
||
|
if Dandelion().hasHash(chunk) and \
|
||
|
i != Dandelion().objectChildStem(chunk):
|
||
|
i.antiIntersectionDelay()
|
||
|
logger.info('%s asked for a stem object we didn\'t offer to it.',
|
||
|
i.destination)
|
||
|
break
|
||
|
try:
|
||
|
payload.extend(protocol.CreatePacket('object',
|
||
|
Inventory()[chunk].payload))
|
||
|
chunk_count += 1
|
||
|
except KeyError:
|
||
|
i.antiIntersectionDelay()
|
||
|
logger.info('%s asked for an object we don\'t have.', i.destination)
|
||
|
break
|
||
|
if not chunk_count:
|
||
|
continue
|
||
|
i.append_write_buf(payload)
|
||
|
logger.debug("%s:%i Uploading %i objects",
|
||
|
i.destination.host, i.destination.port, chunk_count)
|
||
|
uploaded += chunk_count
|
||
|
if not uploaded:
|
||
|
self.stop.wait(1)
|