Коротко о главном
Как всем известно, есть такой замечательный сервис как DropBox. И всем он хорош, только в бесплатной версии для пользователя отводится “всего-ничего” от 2 до 5 гигабайт.
Посидел я, подумал, и решил обойти это ограничение, по крайней мере для некоторых нужд, а именно, для передачи больших объемов данных (превышающих доступный объем) от одного пользователя, одному или нескольким адресатам.
Решение было придумано самое простое: запихиваем требуемые файлы в многотомный архив и передаем через каталог My DropBox по кусочку.
В каких случаях можно использовать такой способ? Ну, например, если требуется передавать много всего разного на несколько компьютеров сразу, либо если нет возможности (желания) открывать прямой доступ к одному из компьютеров участвующих в передаче.
Для реализации функционала была написана программка на Python’е (2.6). Текущая версия работает только под win32.Дистрибутив сконвертированный py2exe в комплекте с readme и исходным кодом здесь — move_big_files.zip (7 мегабайт). В комплекте два исполняемых файла — move_file.exe работающий в консольном режиме и move_file_invis.exe не создающий никаких окон. Последний можно убить только из менеджера процессов, либо при перезагрузке.
Исходный код состоит из двух файлов: move_file.py (основной файл) и single_instance.py (вспомогательная библиотека).
Чуть больше подробностей
Основная задача поставленная при разработке программы: надежная и максимально автоматизированная работа, по возможности устойчивая к внешним воздействиям. Желательно, чтобы программу мог установить неподготовленный пользователь, получая ЦУ по телефону. При этом реализована только минимально-необходимая функциональность. Развитие следует…
У каждого из участников процесса устанавливается по экземпляру программы. В настройках всех
экземпляров задается подкаталог каталога My DropBox через которую происходит обмен (подкаталог должен быть расшарен между пользователями-участниками).
Обмен производится через два каталога обмена — каталог передачи (Outbox) и каталог приема (Inbox)
Как только в Outbox одного из клиентов поступают файлы, данный клиент становится передающим, а остальные- принимающими. После передачи файлы складываются в Inbox принимающих клиентов.
Допускается перезапуск клиентов в процессе передачи, при этом передача приостанавливается до повторного подключения клиента
Можно работать на одном компьютере с несколькими обменными папками, запустив несколько экземпляров программы с разными настройками.
Особенности реализации программы
- Для архивации данных использовался стандартный модуль ZipFile, чтобы не привязываться к архиваторам установленным на компьютере (для упрощения установки неподготовленным пользователем). К сожалению, модуль не поддерживает многотомные архивы, поэтому пришлось создавать один большой архив и разбивать его на куски.
Это приводит к двум ограничениям: если используется файловая система FAT32, то невозможно передавать объемы больше 4 гигабайт за раз и свободное место на диске должно быть как-минимум в два раза больше объема передаваемых данных; - Как уже говорилось выше, пока работаем только под Win32;
- Если в процессе передачи кто-нибудь из клиентов-получателей «зависает» (например, если был выключен компьютер и больше не включался), то передача тоже зависнет, в ожидании получателя. Спасет только ручное удаление флага получения данных (см. ниже) зависшего клиента и перезапуск передающей программы;
- Настройки программы хранятся в файле config.conf в одной папке с программой. Там задаются основные таймауты, названия каталогов и т.д.
Как это работает (много букв!)
Примеров кода приводить не буду в целях экономии места,
подробности можно посмотреть в исходных файлах.
На первый взгляд принцип работы программы очень прост:
На компьютере создаются две папки: Inbox и Outbox. В Outbox кидаем файлы на передачу, в Inbox поступают входящие файлы. Вся обработка файлов идет в промежуточном каталоге Temp.
Обмен файлами идет через общий каталог в каталоге My DropBox. Управляющая информация между клиентами передается флагами. В каталоге передачи создаются 4 каталога для флаг-файлов. Каждая программа может создавать в этих каталогах флаги с именем = id хоста в DropBox (уникальное значение). Всего четыре флага: передачи, приема, завершения приема файла и флаг обработки принятых файлов (склейка томов, распаковка данных).
Режимы работы программы
Программа работает в трех основных режимах:
- Ожидание. Спим и приглядываем за папками. Если в Outbox поступают файлы, начинаем передачу, если появился чужой флаг передачи – начинаем прием;
- Передача. Ставим флаг передачи, пакуем все файлы в Outbox в один многотомный архив (или делаем один архив и бьем на кусочки) и передаем по кусочку принимающим сторонам.
Для этого:
- Получаем список получателей (по флагам приема), перед получением списка нужно выдержать паузу, чтобы получатели успели подключится, освободились от обработки предыдущих пришедших данных (флаг обработки) и т.д.;
- Кидаем кусочек в папку обмена;
- Ждем, пока все получатели не выставят флаги окончания приема файла;
- убиваем флаги приема файла и кусочек в папке обмена и возвращаемся к 2, пока не закончатся файлы
как файлы закончатся, убиваем флаг передачи и переходим к ожиданию.
- Прием:
- Ставим флаг приема;
- Ожидаем поступления кусочка;
- По приходе очередного кусочка копируем во временную папку и ставим флажок приема файла;
- По приходе очередного кусочка копируем во временную папку и ставим флажок приема файла;
- Как только флажок удален передающим, переходим к п.2 и так до удаления флага передачи;
- Как только флаг передачи удаляется, удаляем флаг приема, ставим флаг обработки и распаковываем пришедшие файлы в inbox;
- Удаляем флаг обработки и возвращаемся в режим ожидания.
- Ставим флаг приема;
Все просто и достаточно скучно, но как всегда в процессе реализации возникло несколько задач, которые показались мне интересными. Остановлюсь на них чуть подробнее:
- Нужно чтобы для конкретной обменной папки можно было запустить только один экземпляр программы.
Для решения этой задачи используем мьютексы (модуль SingleInstance). Рецепт взят здесь - Нужно получать конфигурационные параметры DropBox – в частности расположение каталога My DropBox и id хоста.
Решение было найдено в аддонах к DropBox – здесь (подробнее см. метод _get_dropbox_info класса MoveFiles в файле move_file.py ); - Есть некоторая вероятность что процесс передачи одновременно начнут несколько клиентов, необходимо разрешать такие коллизии.
Ставим флаг передачи и ждем отведенный тайм-аут, затем проверяем, есть ли другие флаги передачи. Если флаги есть, передачу продолжает обладатель самого «толстого» id (метод _mark_sending );
- Предполагается передача больших объемов данных, в т.ч. больших файлов, т.е. при создании архива на отправку нужно проверять, закончилось ли копирование конкретного файла в каталог обмена.
Копируемые файлы блокируются в каталоге-приемнике до окончания процесса передачи, поэтому по очереди проверяем все файлы в каталоге-приемнике и готовим к передаче и удаляем все незаблокированные. Файлы которые докопируются позже будут переданы следующей итерацией процесса передачи (метод _prepare_to_send ); - Требуется реализовать подключение к каналу клиентов-получателей только в начале раздачи, поскольку если получатель подключится на раздаче второго и более куска, то он не сможет собрать итоговый файл.
Для этого перед началом передачи дожидаемся пока клиенты не закончат обработку предыдущей передачи ждем отведенный интервал времени с момента постановки флага передачи, после чего дожидаемся пока подключится хоть кто-нибудь и ставим флагу передачи расширение .busy.
Если у флага передачи расширение .busy, никто подключаться не будет… (метод _sending_process ).
Идеи для развития
- Кроссплатформенность;
- Использование многотомных архивов;
- Интеллектуальное разбиение файлов, в зависимости от их размера и формата:
маленькие собираем в кучу, большие разбиваем на кусочки и т.д.; - Иконка в трее и (возможно) GUI, дроплет;
- многофайловая передача для ускорения процесса;
- Многозадачность (многопапочность), т.е. возможность одновременной работы одной программы с несколькими обменными папками.