<s> import logging <EOL> from twisted . internet import defer <EOL> from twisted . protocols . basic import FileSender <EOL> from twisted . python . failure import Failure <EOL> from zope . interface import implements <EOL> from lbrynet . interfaces import IQueryHandlerFactory , IQueryHandler , IBlobSender <EOL> log = logging . getLogger ( __name__ ) <EOL> class BlobRequestHandlerFactory ( object ) : <EOL> implements ( IQueryHandlerFactory ) <EOL> def __init__ ( self , blob_manager , wallet , payment_rate_manager ) : <EOL> self . blob_manager = blob_manager <EOL> self . wallet = wallet <EOL> self . payment_rate_manager = payment_rate_manager <EOL> def build_query_handler ( self ) : <EOL> q_h = BlobRequestHandler ( self . blob_manager , self . wallet , self . payment_rate_manager ) <EOL> return q_h <EOL> def get_primary_query_identifier ( self ) : <EOL> return '<STR_LIT>' <EOL> def get_description ( self ) : <EOL> return "<STR_LIT>" <EOL> class BlobRequestHandler ( object ) : <EOL> implements ( IQueryHandler , IBlobSender ) <EOL> def __init__ ( self , blob_manager , wallet , payment_rate_manager ) : <EOL> self . blob_manager = blob_manager <EOL> self . payment_rate_manager = payment_rate_manager <EOL> self . wallet = wallet <EOL> self . query_identifiers = [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> self . peer = None <EOL> self . blob_data_payment_rate = None <EOL> self . read_handle = None <EOL> self . currently_uploading = None <EOL> self . file_sender = None <EOL> self . blob_bytes_uploaded = <NUM_LIT:0> <EOL> def register_with_request_handler ( self , request_handler , peer ) : <EOL> self . peer = peer <EOL> request_handler . register_query_handler ( self , self . query_identifiers ) <EOL> request_handler . register_blob_sender ( self ) <EOL> def handle_queries ( self , queries ) : <EOL> response = { } <EOL> if self . query_identifiers [ <NUM_LIT:0> ] in queries : <EOL> if not self . handle_blob_data_payment_rate ( queries [ self . query_identifiers [ <NUM_LIT:0> ] ] ) : <EOL> response [ '<STR_LIT>' ] = "<STR_LIT>" <EOL> else : <EOL> response [ '<STR_LIT>' ] = '<STR_LIT>' <EOL> if self . query_identifiers [ <NUM_LIT:1> ] in queries : <EOL> log . debug ( "<STR_LIT>" ) <EOL> response_fields = { } <EOL> response [ '<STR_LIT>' ] = response_fields <EOL> if self . blob_data_payment_rate is None : <EOL> response_fields [ '<STR_LIT:error>' ] = "<STR_LIT>" <EOL> return defer . succeed ( response ) <EOL> else : <EOL> d = self . blob_manager . get_blob ( queries [ self . query_identifiers [ <NUM_LIT:1> ] ] , True ) <EOL> def open_blob_for_reading ( blob ) : <EOL> if blob . is_validated ( ) : <EOL> read_handle = blob . open_for_reading ( ) <EOL> if read_handle is not None : <EOL> self . currently_uploading = blob <EOL> self . read_handle = read_handle <EOL> log . debug ( "<STR_LIT>" , str ( blob ) ) <EOL> response_fields [ '<STR_LIT>' ] = blob . blob_hash <EOL> response_fields [ '<STR_LIT>' ] = blob . length <EOL> return response <EOL> log . debug ( "<STR_LIT>" , str ( blob ) ) <EOL> response_fields [ '<STR_LIT:error>' ] = "<STR_LIT>" <EOL> return response <EOL> d . addCallback ( open_blob_for_reading ) <EOL> return d <EOL> else : <EOL> return defer . succeed ( response ) <EOL> def send_blob_if_requested ( self , consumer ) : <EOL> if self . currently_uploading is not None : <EOL> return self . send_file ( consumer ) <EOL> return defer . succeed ( True ) <EOL> def cancel_send ( self , err ) : <EOL> if self . currently_uploading is not None : <EOL> self . currently_uploading . close_read_handle ( self . read_handle ) <EOL> self . read_handle = None <EOL> self . currently_uploading = None <EOL> return err <EOL> def handle_blob_data_payment_rate ( self , requested_payment_rate ) : <EOL> if not self . payment_rate_manager . accept_rate_blob_data ( self . peer , requested_payment_rate ) : <EOL> return False <EOL> else : <EOL> self . blob_data_payment_rate = requested_payment_rate <EOL> return True <EOL> def send_file ( self , consumer ) : <EOL> def _send_file ( ) : <EOL> inner_d = start_transfer ( ) <EOL> inner_d . addCallback ( lambda _ : set_expected_payment ( ) ) <EOL> inner_d . addBoth ( set_not_uploading ) <EOL> return inner_d <EOL> def count_bytes ( data ) : <EOL> self . blob_bytes_uploaded += len ( data ) <EOL> self . peer . update_stats ( '<STR_LIT>' , len ( data ) ) <EOL> return data <EOL> def start_transfer ( ) : <EOL> self . file_sender = FileSender ( ) <EOL> log . info ( "<STR_LIT>" ) <EOL> assert self . read_handle is not None , "<STR_LIT>" <EOL> d = self . file_sender . beginFileTransfer ( self . read_handle , consumer , count_bytes ) <EOL> return d <EOL> def set_expected_payment ( ) : <EOL> log . info ( "<STR_LIT>" ) <EOL> if self . blob_bytes_uploaded != <NUM_LIT:0> and self . blob_data_payment_rate is not None : <EOL> self . wallet . add_expected_payment ( self . peer , <EOL> self . currently_uploading . length * <NUM_LIT:1.0> * <EOL> self . blob_data_payment_rate / <NUM_LIT:2> ** <NUM_LIT:20> ) <EOL> self . blob_bytes_uploaded = <NUM_LIT:0> <EOL> self . peer . update_stats ( '<STR_LIT>' , <NUM_LIT:1> ) <EOL> return None <EOL> def set_not_uploading ( reason = None ) : <EOL> if self . currently_uploading is not None : <EOL> self . currently_uploading . close_read_handle ( self . read_handle ) <EOL> self . read_handle = None <EOL> self . currently_uploading = None <EOL> self . file_sender = None <EOL> if reason is not None and isinstance ( reason , Failure ) : <EOL> log . info ( "<STR_LIT>" , reason . getErrorMessage ( ) ) <EOL> return _send_file ( ) </s>
