def test_can_create_file(self): expected_stream_hash = "41e6b247d923d191b154fb6f1b8529d6ddd6a73d65c35" \ "7b1acb742dd83151fb66393a7709e9f346260a4f4db6de10c25" expected_sd_hash = "db043b44384c149126685990f6bb6563aa565ae331303d522" \ "c8728fe0534dd06fbcacae92b0891787ad9b68ffc8d20c1" filename = 'test.file' lbry_file = yield self.create_file(filename) sd_hash = yield self.storage.get_sd_blob_hash_for_stream( lbry_file.stream_hash) # read the sd blob file sd_blob = self.blob_manager.blobs[sd_hash] sd_reader = BlobStreamDescriptorReader(sd_blob) sd_file_info = yield sd_reader.get_info() # this comes from the database, the blobs returned are sorted sd_info = yield get_sd_info(self.storage, lbry_file.stream_hash, include_blobs=True) self.assertDictEqual(sd_info, sd_file_info) self.assertListEqual(sd_info['blobs'], sd_file_info['blobs']) self.assertEqual(sd_info['stream_hash'], expected_stream_hash) self.assertEqual(len(sd_info['blobs']), 3) self.assertNotEqual(sd_info['blobs'][0]['length'], 0) self.assertNotEqual(sd_info['blobs'][1]['length'], 0) self.assertEqual(sd_info['blobs'][2]['length'], 0) self.assertEqual(expected_stream_hash, lbry_file.stream_hash) self.assertEqual(sd_hash, lbry_file.sd_hash) self.assertEqual(sd_hash, expected_sd_hash) blobs = yield self.blob_manager.get_all_verified_blobs() self.assertEqual(3, len(blobs)) num_should_announce_blobs = yield self.blob_manager.count_should_announce_blobs( ) self.assertEqual(2, num_should_announce_blobs)
def download_it(peer, timeout, blob_hash): tmp_dir = yield threads.deferToThread(tempfile.mkdtemp) storage = SQLiteStorage(tmp_dir, reactor) yield storage.setup() tmp_blob_manager = DiskBlobManager(tmp_dir, storage) config = {'auto_connect': True} if conf.settings['lbryum_wallet_dir']: config['lbryum_wallet_dir'] = conf.settings['lbryum_wallet_dir'] config['use_keyring'] = False config['blockchain_name'] = conf.settings['blockchain_name'] config['lbryum_servers'] = [] wallet = LbryWalletManager.from_lbrynet_config(config, storage) downloader = SinglePeerDownloader() downloader.setup(wallet) try: blob_downloaded = yield downloader.download_blob_from_peer( peer, timeout, blob_hash, tmp_blob_manager) if blob_downloaded: log.info("SUCCESS!") blob = yield tmp_blob_manager.get_blob(blob_hash) pprint(blob) if not blob.verified: log.error("except that its not verified....") else: reader = BlobStreamDescriptorReader(blob) info = None for x in range(0, 3): try: info = yield reader.get_info() except ValueError: pass if info: break # there's some kind of race condition where it sometimes doesnt write the blob to disk in time time.sleep(0.1) if info is not None: pprint(info) for content_blob in info['blobs']: if 'blob_hash' in content_blob: yield download_it(peer, timeout, content_blob['blob_hash']) else: log.error("Download failed") finally: yield tmp_blob_manager.stop() yield threads.deferToThread(shutil.rmtree, tmp_dir) defer.returnValue(True)
def download_it(peer, timeout, blob_hash): tmp_dir = yield threads.deferToThread(tempfile.mkdtemp) announcer = DummyHashAnnouncer() tmp_blob_manager = DiskBlobManager(announcer, tmp_dir, tmp_dir) config = {'auto_connect': True} if conf.settings['lbryum_wallet_dir']: config['lbryum_path'] = conf.settings['lbryum_wallet_dir'] storage = Wallet.InMemoryStorage() wallet = Wallet.LBRYumWallet(storage, config) downloader = SinglePeerDownloader() downloader.setup(wallet) try: blob_downloaded = yield downloader.download_blob_from_peer( peer, timeout, blob_hash, tmp_blob_manager) if blob_downloaded: log.info("SUCCESS!") blob = yield tmp_blob_manager.get_blob(blob_hash) pprint(blob) if not blob.verified: log.error("except that its not verified....") else: reader = BlobStreamDescriptorReader(blob) info = None for x in range(0, 3): try: info = yield reader.get_info() except ValueError: pass if info: break time.sleep( 0.1 ) # there's some kind of race condition where it sometimes doesnt write the blob to disk in time if info is not None: pprint(info) for content_blob in info['blobs']: if 'blob_hash' in content_blob: yield download_it(peer, timeout, content_blob['blob_hash']) else: log.error("Download failed") finally: yield tmp_blob_manager.stop() yield threads.deferToThread(shutil.rmtree, tmp_dir) defer.returnValue(True)
def _on_completed_blob(self, blob, response_key): yield self.blob_manager.blob_completed(blob, should_announce=False) if response_key == RECEIVED_SD_BLOB: sd_info = yield BlobStreamDescriptorReader(blob).get_info() yield save_sd_info(self.blob_manager, blob.blob_hash, sd_info) yield self.blob_manager.set_should_announce(blob.blob_hash, True) # if we already have the head blob, set it to be announced now that we know it's # a head blob d = self.check_head_blob_announce(sd_info['stream_hash']) else: d = defer.succeed(None) stream_hash = yield self.storage.get_stream_of_blob(blob.blob_hash) if stream_hash is not None: blob_num = yield self.storage.get_blob_num_by_hash(stream_hash, blob.blob_hash) if blob_num == 0: sd_hash = yield self.storage.get_sd_blob_hash_for_stream(stream_hash) yield self.blob_manager.set_should_announce(blob.blob_hash, True) # if we already have the sd blob, set it to be announced now that we know it's # a sd blob d.addCallback(lambda _: self.check_sd_blob_announce(sd_hash)) yield self.close_blob() yield d log.info("Received %s", blob) yield self.send_response({response_key: True})
def get_descriptor_response(self, sd_blob): if sd_blob.get_is_verified(): sd_info = yield BlobStreamDescriptorReader(sd_blob).get_info() yield save_sd_info(self.blob_manager, sd_blob.blob_hash, sd_info) yield self.storage.verify_will_announce_head_and_sd_blobs(sd_info['stream_hash']) response = yield self.request_needed_blobs({SEND_SD_BLOB: False}, sd_info['stream_hash']) else: self.incoming_blob = sd_blob self.receiving_blob = True self.handle_incoming_blob(RECEIVED_SD_BLOB) response = {SEND_SD_BLOB: True} defer.returnValue(response)
def check_sd_blob_announce(self, sd_hash): if sd_hash in self.blob_manager.blobs: sd_blob = self.blob_manager.blobs[sd_hash] if sd_blob.get_is_verified(): should_announce = yield self.blob_manager.get_should_announce(sd_hash) if should_announce == 0: yield self.blob_manager.set_should_announce(sd_hash, 1) log.info("Discovered previously completed sd blob (%s), " "setting it to be announced", sd_hash[:8]) stream_hash = yield self.storage.get_stream_hash_for_sd_hash(sd_hash) if not stream_hash: log.info("Adding blobs to stream") sd_info = yield BlobStreamDescriptorReader(sd_blob).get_info() yield save_sd_info(self.blob_manager, sd_hash, sd_info) defer.returnValue(None)
def test_can_create_file(self): expected_stream_hash = "41e6b247d923d191b154fb6f1b8529d6ddd6a73d65c35" \ "7b1acb742dd83151fb66393a7709e9f346260a4f4db6de10c25" expected_sd_hash = "40c485432daec586c1a2d247e6c08d137640a5af6e81f3f652" \ "3e62e81a2e8945b0db7c94f1852e70e371d917b994352c" filename = 'test.file' lbry_file = yield self.create_file(filename) sd_hash = yield self.storage.get_sd_blob_hash_for_stream( lbry_file.stream_hash) # read the sd blob file sd_blob = self.blob_manager.blobs[sd_hash] sd_reader = BlobStreamDescriptorReader(sd_blob) sd_file_info = yield sd_reader.get_info() # this comes from the database, the blobs returned are sorted sd_info = yield get_sd_info(self.storage, lbry_file.stream_hash, include_blobs=True) self.maxDiff = None unicode_sd_info = json.loads( json.dumps(sd_info, sort_keys=True, cls=JSONBytesEncoder)) self.assertDictEqual(unicode_sd_info, sd_file_info) self.assertEqual(sd_info['stream_hash'], expected_stream_hash) self.assertEqual(len(sd_info['blobs']), 3) self.assertNotEqual(sd_info['blobs'][0]['length'], 0) self.assertNotEqual(sd_info['blobs'][1]['length'], 0) self.assertEqual(sd_info['blobs'][2]['length'], 0) self.assertEqual(expected_stream_hash, lbry_file.stream_hash) self.assertEqual(sd_hash, lbry_file.sd_hash) self.assertEqual(sd_hash, expected_sd_hash) blobs = yield self.blob_manager.get_all_verified_blobs() self.assertEqual(3, len(blobs)) num_should_announce_blobs = yield self.blob_manager.count_should_announce_blobs( ) self.assertEqual(2, num_should_announce_blobs)
def _on_completed_blob(self, blob, response_key): yield self.blob_manager.blob_completed(blob, should_announce=False) if response_key == RECEIVED_SD_BLOB: sd_info = yield BlobStreamDescriptorReader(blob).get_info() yield save_sd_info(self.blob_manager, blob.blob_hash, sd_info) yield self.blob_manager.set_should_announce(blob.blob_hash, True) else: stream_hash = yield self.storage.get_stream_of_blob(blob.blob_hash) if stream_hash is not None: blob_num = yield self.storage.get_blob_num_by_hash(stream_hash, blob.blob_hash) if blob_num == 0: yield self.blob_manager.set_should_announce(blob.blob_hash, True) yield self.close_blob() log.info("Received %s", blob) yield self.send_response({response_key: True})
def get_descriptor_response(self, sd_blob): if sd_blob.get_is_verified(): # if we already have the sd blob being offered, make sure we have it and the head blob # marked as such for announcement now that we know it's an sd blob that we have. yield self.check_sd_blob_announce(sd_blob.blob_hash) try: stream_hash = yield self.storage.get_stream_hash_for_sd_hash( sd_blob.blob_hash) except NoSuchSDHash: sd_info = yield BlobStreamDescriptorReader(sd_blob).get_info() stream_hash = sd_info['stream_hash'] yield save_sd_info(self.blob_manager, sd_blob.blob_hash, sd_info) yield self.check_head_blob_announce(stream_hash) response = yield self.request_needed_blobs({SEND_SD_BLOB: False}, sd_blob) else: self.incoming_blob = sd_blob self.receiving_blob = True self.handle_incoming_blob(RECEIVED_SD_BLOB) response = {SEND_SD_BLOB: True} defer.returnValue(response)
def read_sd_file(self, sd_blob): reader = BlobStreamDescriptorReader(sd_blob) return save_sd_info(self.stream_info_manager, reader, ignore_duplicate=True)