def recv_iftd_sender_data( xmit_id, job_attrs, available_protos, receiver_connect_dict, chunk_hashes, sender_xmlrpc_url ): """ Called by the iftd sender (remote) on the iftd receiver (local), this begins an intelligent file transmission. @arg xmit_id: Numerical ID of this transfer (the SHA-1 hash of the job) @arg job_attrs: Known data about the file (dictionary). Should contain JOB_ATTR_SRC_NAME and JOB_ATTR_FILE_HASH @arg available_protocols: List of protocol names that are available to the sender (these are all senders, and they don't end in "_sender") @arg receiver_connect_dict: Dictionary mapping receiver protocol name to connection attributes needed to start up @arg chunk_hashes: List of SHA-1 hashes of each file chunk @arg sender_xmlrpc_url URL for the receiver to contact the sender to ACK the transmission """ error_rc = [xmit_id, None, None, None, None] # sanity check if iftfile.JOB_ATTR_SRC_NAME not in job_attrs or iftfile.JOB_ATTR_FILE_HASH not in job_attrs: return error_rc from iftdata import RECV_FILES_DIR # access control check if not os.path.abspath(job_attrs.get( iftfile.JOB_ATTR_DEST_NAME )).startswith( RECV_FILES_DIR, 0, len(RECV_FILES_DIR )): iftlog.log(5, "recv_iftd_sender_data: request for " + job_attrs.get(iftfile.JOB_ATTR_SRC_NAME) + " to " + job_attrs.get( iftfile.JOB_ATTR_DEST_NAME ) + " cannot be serviced, since it is not going to be sent to " + RECV_FILES_DIR ) return error_rc features = iftstats.extract_features( job_attrs ) my_protos = proto_names( receivers( list_protocols() ) ) # get the rank best_proto_name = iftstats.best_protocol( features ) best_proto = None if best_proto_name != None: best_proto = proto_names( [best_proto_name] )[0] available_proto_names = proto_names( available_protos ) # remove any available protocols that we don't have receivers for usable_protos = [] for proto in my_protos: if proto in available_proto_names: usable_protos.append( proto ) # the best protocol may not be usable... if best_proto != None and best_proto not in usable_protos: best_proto = None # we're in trouble if there aren't any protocols usable... if len(usable_protos) == 0 and best_proto == None: return error_rc # cannot receive! # make chunk directory in preparation for receiving pieces (i.e. from an active sender) rc = iftfile.make_chunks_dir( job_attrs.get( iftfile.JOB_ATTR_DEST_NAME ), job_attrs.get( iftfile.JOB_ATTR_FILE_HASH ) ) if rc != 0: return error_rc # error! # start up a transfer processor with the available protocols proto_instances = [] for proto in usable_protos: proto = proto + "_receiver" # if it's available, then there's a receiver available p = None try: p = copy.deepcopy( PROTOCOLS[proto] ) except Exception, inst: iftlog.log(5, "ERROR: could not clone protocol " + proto) continue proto_instances.append( p )
iftlog.exception( "iftreceive: could not get sender data", inst) return E_NO_CONNECT proto_active_table = {} if remote_iftd: for i in xrange( 0, len(sender_available_protos) ): proto_active_table[sender_available_protos[i]] = active_flags[i] # map each protocol to its active or inactive boolean usable_protos = proto_names( available_protocols ) if remote_iftd: if len(available_protocols) > 1: # we have a choice... # now we have the protocols available to both of us. # get the best protocol features = iftstats.extract_features( job.attrs ) best_proto = iftstats.best_protocol( features ) if best_proto != None: usable_protos = proto_names( [best_proto] + sender_available_protos ) # make chunk directory in preparation for receiving pieces (i.e. from an active sender) rc = iftfile.make_chunks_dir( job.get_attr( iftfile.JOB_ATTR_DEST_NAME ), job.get_attr( iftfile.JOB_ATTR_FILE_HASH ) ) if rc != 0: iftlog.log(5, "iftreceive: could not make chunks directory") return rc # record local chunk dir job.set_attr( iftfile.JOB_ATTR_DEST_CHUNK_DIR, iftfile.get_chunks_dir( job.get_attr( iftfile.JOB_ATTR_DEST_NAME ), job.get_attr( iftfile.JOB_ATTR_FILE_HASH ), remote_iftd )) # start up a transfer processor with the available protocols