Improved resource transfers over unreliable links

This commit is contained in:
Mark Qvist 2023-11-04 18:05:20 +01:00
parent db1cdec2a2
commit c4d0f08767

View File

@ -26,6 +26,7 @@ import bz2
import math import math
import time import time
import threading import threading
from threading import Lock
from .vendor import umsgpack as umsgpack from .vendor import umsgpack as umsgpack
from time import sleep from time import sleep
@ -47,7 +48,7 @@ class Resource:
WINDOW = 4 WINDOW = 4
# Absolute minimum window size during transfer # Absolute minimum window size during transfer
WINDOW_MIN = 1 WINDOW_MIN = 2
# The maximum window size for transfers on slow links # The maximum window size for transfers on slow links
WINDOW_MAX_SLOW = 10 WINDOW_MAX_SLOW = 10
@ -103,7 +104,7 @@ class Resource:
PART_TIMEOUT_FACTOR = 4 PART_TIMEOUT_FACTOR = 4
PART_TIMEOUT_FACTOR_AFTER_RTT = 2 PART_TIMEOUT_FACTOR_AFTER_RTT = 2
MAX_RETRIES = 8 MAX_RETRIES = 16
MAX_ADV_RETRIES = 4 MAX_ADV_RETRIES = 4
SENDER_GRACE_TIME = 10 SENDER_GRACE_TIME = 10
RETRY_GRACE_TIME = 0.25 RETRY_GRACE_TIME = 0.25
@ -170,7 +171,8 @@ class Resource:
resource.receiving_part = False resource.receiving_part = False
resource.consecutive_completed_height = 0 # TODO: Recheck
resource.consecutive_completed_height = -1
if not resource.link.has_incoming_resource(resource): if not resource.link.has_incoming_resource(resource):
resource.link.register_incoming_resource(resource) resource.link.register_incoming_resource(resource)
@ -366,7 +368,8 @@ class Resource:
if advertise: if advertise:
self.advertise() self.advertise()
else: else:
pass self.receive_lock = Lock()
def hashmap_update_packet(self, plaintext): def hashmap_update_packet(self, plaintext):
if not self.status == Resource.FAILED: if not self.status == Resource.FAILED:
@ -623,8 +626,7 @@ class Resource:
def receive_part(self, packet): def receive_part(self, packet):
while self.receiving_part: with self.receive_lock:
sleep(0.001)
self.receiving_part = True self.receiving_part = True
self.last_activity = time.time() self.last_activity = time.time()
@ -658,8 +660,9 @@ class Resource:
part_data = packet.data part_data = packet.data
part_hash = self.get_map_hash(part_data) part_hash = self.get_map_hash(part_data)
i = self.consecutive_completed_height consecutive_index = self.consecutive_completed_height if self.consecutive_completed_height >= 0 else 0
for map_hash in self.hashmap[self.consecutive_completed_height:self.consecutive_completed_height+self.window]: i = consecutive_index
for map_hash in self.hashmap[consecutive_index:consecutive_index+self.window]:
if map_hash == part_hash: if map_hash == part_hash:
if self.parts[i] == None: if self.parts[i] == None:
@ -728,11 +731,25 @@ class Resource:
hashmap_exhausted = Resource.HASHMAP_IS_NOT_EXHAUSTED hashmap_exhausted = Resource.HASHMAP_IS_NOT_EXHAUSTED
requested_hashes = b"" requested_hashes = b""
offset = (1 if self.consecutive_completed_height > 0 else 0) i = 0; pn = self.consecutive_completed_height+1
i = 0; pn = self.consecutive_completed_height+offset
search_start = pn search_start = pn
search_size = self.window
for part in self.parts[search_start:search_start+self.window]: # TODO: Remove
# tpm = []
# tpi = 0
# try:
# for p in self.parts:
# if p == None:
# tpm.append(None)
# else:
# tpm.append(tpi)
# tpi+=1
# except Exception as e:
# print(str(e))
# RNS.log(f"Partmap: "+str(tpm))
for part in self.parts[search_start:search_start+search_size]:
if part == None: if part == None:
part_hash = self.hashmap[pn] part_hash = self.hashmap[pn]
if part_hash != None: if part_hash != None:
@ -752,7 +769,6 @@ class Resource:
hmu_part += last_map_hash hmu_part += last_map_hash
self.waiting_for_hmu = True self.waiting_for_hmu = True
requested_data = b""
request_data = hmu_part + self.hash + requested_hashes request_data = hmu_part + self.hash + requested_hashes
request_packet = RNS.Packet(self.link, request_data, context = RNS.Packet.RESOURCE_REQ) request_packet = RNS.Packet(self.link, request_data, context = RNS.Packet.RESOURCE_REQ)
@ -908,8 +924,7 @@ class Resource:
else: else:
self.progress_total_parts = float(self.total_parts) self.progress_total_parts = float(self.total_parts)
progress = min(1.0, self.processed_parts / self.progress_total_parts)
progress = self.processed_parts / self.progress_total_parts
return progress return progress
def get_transfer_size(self): def get_transfer_size(self):