def sync_file_from_dropbox(node_id, use_ust=True, callback=None): """ Sync file which was updated on dropbox Arguments: node_id: updated file use_ust: if True, process remove in User Synchronous mode """ node, db_sess = _get_node(node_id) if use_ust: if django_settings.ASYNC_DROPBOX: yield gen.Task(async_ust_start, node.user) else: ust_start(node.user) l.info("sync_file_FROM_dropbox: '%s'" % (node.db_path, )) try: # Read file content from dropbox if django_settings.ASYNC_DROPBOX: yield_key = object() db_sess.read_file(encode_if_unicode(node.db_path), callback=(yield gen.Callback(yield_key))) content = yield gen.Wait(yield_key) else: content = db_sess.read_file(encode_if_unicode(node.db_path)) # And save it to local storage _save_and_convert(node, content) # User may want to know that this file was synced append_to_changes_list(node.user, node.db_path) except Exception, e: err_msg = "SYNC_file_from_dropbox: '%s' (%s)" %\ (node.db_path, e,) l.error(err_msg) raise MDBException("ERROR: "+err_msg)
def sync_dir_from_dropbox(node_id, use_ust=True, callback=None): """ Sync dir which was updated on dropbox The whole dir is checked for added/removed files and dirs and each entry is updated using appropriate method Arguments: node_id: updated dir use_ust: if True, process remove in User Synchronous mode """ node, db_sess = _get_node(node_id) if use_ust: if django_settings.ASYNC_DROPBOX: yield gen.Task(async_ust_start, node.user) else: ust_start(node.user) # We need to try/except the whole block to make sure # that we call ust_end() before leaving the method try: if django_settings.ASYNC_DROPBOX: resp = yield gen.Task(db_sess.dir_changed, node.db_path, node.hash) else: resp = db_sess.dir_changed(node.db_path, node.hash) if not resp: l.info("sync_DIR_FROM_dropbox: '%s':'%s' skipping (same hash)" %\ (node.user.username, node.db_path, )) else: # User may want to know that this dir was updated append_to_changes_list(node.user, node.db_path) # Retrieve list of files and dirs from dropbox for given directory if django_settings.ASYNC_DROPBOX: file_dicts = yield gen.Task(db_sess.get_files_as_dicts, node.db_path) else: file_dicts = db_sess.get_files_as_dicts(node.db_path) if file_dicts: yield_keys = [] # Check each file in directory for updates # We go through OUR file list and compare each file's # .last_modified date with the one in matching dropbox file for child in node.get_children(): if not child.is_file: continue file_dict = dicts_find(file_dicts, child.db_path) if file_dict and dict_last_modified(file_dict) > child.last_modified: # File in dropbox was changed: remember new mod date and sync it MDBTree.objects.filter(pk=child.pk).update( last_modified = dict_last_modified(file_dict), ) if django_settings.ASYNC_DROPBOX: yield_key = object() yield_keys.append(yield_key) local_callback = (yield gen.Callback(yield_key)) else: local_callback = None sync_file_from_dropbox(child.id, use_ust=False, callback=local_callback) # Wait for all add_file_from_dropbox() to complete if django_settings.ASYNC_DROPBOX and yield_keys: yield gen.WaitAll(yield_keys) # Get only list of files as a set # And see what's new/missing db_files = set(dicts_to_paths(file_dicts, files_only=True)) if db_files: # Get list of files in dir from database known_files = set(node.get_paths('FILES')) yield_keys = [] # Add new files from dropbox to our database for new_file in db_files - known_files: if new_file != '': db_last_modified =\ dict_last_modified(dicts_find(file_dicts, new_file)) if django_settings.ASYNC_DROPBOX: yield_key = object() yield_keys.append(yield_key) local_callback = (yield gen.Callback(yield_key)) else: local_callback = None add_file_from_dropbox(node.id, new_file, db_last_modified, use_ust=False, callback=local_callback) # Wait for all add_file_from_dropbox() to complete if django_settings.ASYNC_DROPBOX and yield_keys: yield gen.WaitAll(yield_keys) # Remove files deleted from dropbox from our database for missing_file in known_files - db_files: if missing_file != '': missing_node = get_node_by_path(node.user, missing_file) # Only remove it from our database and server if django_settings.ASYNC_DROPBOX: yield_key = object() remove_node_as_file(missing_node.id, skip_dropbox=True, use_ust=False, callback=(yield gen.Callback(yield_key))) yield gen.Wait(yield_key) else: remove_node_as_file(missing_node.id, skip_dropbox=True, use_ust=False) # Get only list of dirs as a set # And see what's new/missing db_dirs = set(dicts_to_paths(file_dicts, dirs_only=True)) yield_keys = [] if db_dirs: # Get list of dirs in dir from database known_dirs = set(node.get_paths('DIRS')) # Add new dirs from dropbox to our database for new_dir in db_dirs - known_dirs: if new_dir != '': if django_settings.ASYNC_DROPBOX: yield_key = object() yield_keys.append(yield_key) local_callback = (yield gen.Callback(yield_key)) else: local_callback = None add_dir_from_dropbox(node.id, new_dir, use_ust=False, callback=local_callback) #ust_store_id(async_res.task_id, node.user) # Wait for all add_dir_from_dropbox() to complete if django_settings.ASYNC_DROPBOX and yield_keys: yield gen.WaitAll(yield_keys) # Remove dirs, which are missing from dropbox from our database for missing_dir in known_dirs - db_dirs: if missing_dir != '' and missing_dir != '/' : missing_node = get_node_by_path(node.user, missing_dir) # Only remove it from our database and server if django_settings.ASYNC_DROPBOX: yield_key = object() remove_node_as_dir(missing_node.id, skip_dropbox=True, use_ust=False, callback=(yield gen.Callback(yield_key))) yield gen.Wait(yield_key) else: remove_node_as_dir(missing_node.id, skip_dropbox=True, use_ust=False) # Save new hash for future checks MDBTree.objects.filter(pk=node.pk).update( hash = resp['hash'], last_synced = datetime.utcnow(), ) except Exception, e: l.error("sync_DIR_FROM_dropbox: '%s':'%s' (%s)" %\ (node.user.username, node.db_path, e, )) raise MDBException("ERROR: "+e.message)