Яндекс.Диск - хмарний сервіс компанії Яндекс. Раніше з Linux працював тільки через WebDAV, для чого були придатні лише деякі файлові менеджери, або монтування за допомогою davfs2.

Тепер випущений клієнт. Консольний, вихідні коди закриті - але настроювати зручніше, ніж davfs2, а синхронізація локальних файлів не вимагає скриптової обв'язки. Досить встановити програму, налаштувати підключення, а потім вибрати каталоги, які підлягають або не підлягають синхронізації. У нього є вся основна функціональність, яка є у клієнтів для OS X і Windows, і навіть більше (сімлінки!), і одна особливість - він консольний.

Яндекс.Диск

Нижче читайте про те, як він налаштовується, що конкретно вміє, і про те, як саме він влаштований і що в ньому було непросто зробити.

Встановлення

Встановити його можна тут. Відразу після установки пакета в терміналі з'явиться команда yandex-disk, через яку в подальшому і йде робота з хмарою Яндекса. Після цього потрібно вручну запустити команду setup.

Майстер налаштування дозволяє в режимі діалогу вибрати папку для синхронізації, включити автозапуск при старті системи, налаштувати роботу через проксі-сервер (якщо звичайно ви ним користуєтеся) і авторизуватися в Яндекс.Диск. При налаштуванні вручну насамперед необхідно авторизуватися. Після цього в папці .config, розташованої в домашньому каталозі, буде створений конфіг, в якому можна буде налаштувати шлях до папки синхронізації (можна вказати в консолі вручну), прописати шлях до файлу токену, вказати папки, які будуть чи не будуть синхронізуватися, і прописати налаштування проксі-сервера.

Команди

Підготовча робота закінчена, залишилося запустити демон однієї з команд. Вони дозволять вам синхронізувати файли і папки і користуватися ними скрізь, де є інтернет .

  • sync - запустить демон, синхронізує все, що знаходиться в папці Диска, і зупинить демон.
  • start - зробить те ж саме, але без зупинки демона після завершення синхронізації. При використанні start демон залишається запущений і всі зміни, що відбуваються в папці Диска , будуть синхронізуватися автоматично.
  • Ввівши в терміналі stop, можна в будь-який момент зупинити запущений демон, якщо він вам заважає.
  • Командою status можна дізнатися , в якому статусі знаходиться ядро ​​синхронізації.

Працювати з папкою диска можна як з терміналу, так і з Nautilus'a.

Що вміє

Консольний клієнт дозволяє поділитися файлом або текою за допомогою команди publish (якщо файл знаходиться не в папці диска, перед публікацією він буде туди скопійований). Посилання буде доступна в терміналі, і будь-яка людина, перейшовши по ньому, зможе подивитися або зберегти собі опублікований вами файл або теку. Якщо випадково був опублікований не той файл, за допомогою команди unpublish можна закрити доступ до публічного об'єкту.

У Яндекс.Диск можлива вибіркова синхронізація. Команда exclude дозволить виключити папку з синхронізації: всі зміни, зроблені в ній після цього, не будуть відправлені в хмару.

Опція read-only дозволить міняти файли локально, без заливки їх в хмару. При виникненні конфліктів з локальними змінами, останні будуть збережені в перейменованих файлах, а зміни з хмари будуть синхронізовані. Опція overwrite буде перезаписувати локально змінені файли в режимі read-only .

Не можемо не похвалитися самим цікавим нововведенням в ядрі синхронізації - відтепер ми підтримуємо синхронізацію символічних посиланнь (symlink)! Якщо виникнуть труднощі і питання у використанні консольного клієнта команди man і help просто і доступно допоможуть у них розібратися.

Як зроблено

Щоб у майбутньому код можна було використовувати для реалізації клієнтів під різні ОС, було прийнято рішення писати його на C++. Специфічні для різних операційних систем шматки коду ми винесли в окремі функції чи класи, а під кожну платформу писали свою реалізацію. В якості основних кроссплатформенних бібліотек ми взяли Boost, OpenSSL і JsonCpp, а системою контролю версій став git. Клієнт під Linux збирався за допомогою autoconf. Код писався і налагоджувався у зв'язці KDevelop + консольний gdb або в Qt Creator'е (залежно від уподобань розробника) .

Взаємодія з хмарою і синхронізація відбувається за допомогою бібліотеки ядра Яндекс.Диск , яку використовують десктопні клієнти сервісу.

Як працює

Консольний клієнт складається з двох частин: демона і клієнта. Спілкуються вони за допомогою текстових пакетів містять json - повідомлення, що посилаються через сокети (на Linux і Mac OS X використовуються unix - domain сокети). Асинхронна робота реалізована за допомогою бібліотеки boost::asio. Синхронізація доступу до даних реалізується через boost::asio::io_service::strand, що дозволяє не думати про проблему одночасного доступу до даних декількох потоків, а також виключає появу deadlock-ів.

Для локалізації ми використовуємо бібліотеку boost::locale. Текст всередині клієнта закодований в utf 8 і за необхідності перетворюється в специфічному для кожної операційної системи коді. Моніторинг файлової системи для Linux використовує inotify, чудово вписуються в асинхронну роботу boost::asio.

Як влаштована синхронізація

Синхронізація - серце Яндекс.Диск, його ключова можливість. Завдання синхронізації файлового дерева з хмарою ділиться на кілька незалежних частин.

1. Моніторинг файлової системи. Ядро синхронізації Яндекс.Диск проектувалося і створювалося як переносима абстракція, здатна виконувати поставлені завдання на всіх підтримуваних платформах. Але така проблема, як моніторинг файлової системи не реалізується ні стандартної бібліотекою C++, ні навіть такими монстрами як boost. Більше того, навіть використовуючи «рідне» API операційної системи, ми отримуємо набір подій, специфічний для кожної платформи.

Для моніторингу файлової системи був спроектований інтерфейс «спостерігача» , здатного стежити за подіями в певній директорії і повертає список подій, що відбулися в ній. Причому для кожної підтримуваної платформи набір цих подій відрізняється. Наприклад, Mac OS X здатна повідомити тільки про факт якогось зміни в одній з дочірніх директоріях без деталізації. А ось Windows і Linux повертають повний набір, включаючи створення, видалення, модифікацію і переміщення об'єктів. Хоча практика показувала, що подіям на платформі Windows довіряти не варто і самим надійним варіантом залишається лістинг директорії після отримання оповіщення.

2. Індексація локальних файлів і директорій. Для контролю цілісності та реалізації дельта -оновлення файлів ядро синхронізації Яндекс.Диск використовує дайджести - набори контрольних сум файлу і окремих його частин. Для всього файлу ми розраховуємо стійкий хеш SHA-256 і набір менш стійких сум для окремих блоків. Кожен файл, що знаходиться в папці Яндекс.Диск і не потрапляє до списку винятків, повинен бути проіндексований. Але обчислення хеша SHA-256 досить дорога операція, а розрахунок хешей при кожному запуску ПО був б великою витратою ресурсів. Тому після того, як завершується індексація файлу , ядро синхронізації зберігає отриманий дайджест в «банці» - спеціальному сховищі, що знаходиться у службовій директорії Яндекс.Диск. Для пошуку дайджестів в сховище використовується унікальний ідентифікатор файлу - inode (розмір і час останньої зміни) . На жаль, подібний підхід не позбавлений недоліків. Наприклад, багато файлів - криптоконтейнера зберігають час останньої модифікації незмінним навіть після запису .

Напевно, крім тонкощів роботи з символічними посиланнями , нічого в лістингу директорій не представляє особливого інтересу. Для успішного завершення синхронізації ядро повинне виявляти і виключати з синхронізації циклічні гілки .

Взагалі , символічні посилання - це справжня «головна біль» для ядра синхронізації. Вони можуть вказувати у довільні місця файлової системи , і ні до всіх з них можна застосовувати однакові правила синхронізації. Наприклад , пакети додатків Mac OS X дуже часто містять в собі символічні посилання на директорії системних бібліотек , і їх синхронізація в хмару була б небажана - особливо між різними версіями ОС . Але в той же час можливість синхронізувати додаткові директорії за допомогою символічних посилань - дуже приваблива можливість , упускати яку не хотілося.

Тому для синхронізації символічних посилань була введена особлива політика , завдяки якій ядро ​​може вибирати специфічний варіант синхронізації для кожної символічного посилання - залежно від розташування об'єкта , на який вона вказує.

3. Отримання дерева хмарної файлової системи. Для вирішення проблеми синхронізації мало мати локальну файлову структуру і дайджести файлів - необхідно отримати поточний стан файлової системи в хмарі. Якби ядру синхронізації щоразу доводилося обходити дерево за допомогою методу PROPFIND , то кожен цикл синхронізації займав би невиправдано багато часу і створював би зайве навантаження на канал. Тому ПО Яндекс.Диск використовує спеціальний API , який дає можливість отримувати поточний стан дерева файлів у хмарі і зміни, що відбулися в ньому , починаючи з деякого відомого моменту, що визначається версією дерева.

4. Отримання оповіщень про зміну хмарної файлової системи. Синхронізація файлів в реальному часі вимагає своєчасного одержання оповіщень про зміни , що сталися з файлами в хмарі. Можна було б використовувати періодичний опитування сервера клієнтами , але , оцінивши можливу кількість клієнтів , ми прийшли до висновку , що такий підхід виявиться слабо масштабованим і приведе до швидкої перевантаженні інфраструктури сервісу. Після недовгих пошуків ми зупинилися на протоколі XMPP . Одна з його реалізацій вже довгий час працює в Яндексі. Вона була розроблена командою , яка пізніше займалися створенням сервера WebDAV для проекту Яндекс.Диск , тому складнощів з інтеграцією цього протоколу не виникло.

Зараз пуш -сповіщення , оброблювані ядром синхронізації , включають в себе не тільки події, що відбулися безпосередньо з файлами або папками в хмарі Яндекс.Диск , але і різні сервісні повідомлення. Наприклад про видачу додаткового місця або діях інших користувачів у спільних папках . Додавання цих подій до наявного Протоколу не викликало великих труднощів завдяки розширюваності XMPP , що в черговий раз підтвердило правильність нашого вибору.

5. Створення списку операцій синхронізації. Після того як у розпорядженні ядра синхронізації виявляються обидва дерева файлів - локальне та віддалене - можна приступати до самої процедури синхронізації. Для цього застосовується спеціальний алгоритм порівняння дерев , що приймає на вхід окрім двох згаданих дерев , ще й третє - останнє синхронізоване . В результаті роботи алгоритму виходить список операцій , які необхідно здійснити над локальними і віддаленими файлами і директорій для приведення дерев до загального вигляду .

6. Обробка черги операцій синхронізації. Створення списку операцій для локального та віддаленого дерев відбувається незалежно. В результаті можуть з'явитися конфліктуючі операції . Наприклад , видалення в хмарі файлу , який був у ньому змінено і ще не синхронізований локально , або зміна файлу одночасно локально і в хмарі. Конфлікти модифікації / видалення завжди вирішуються ядром на користь модифікації , а конфлікти подвійний модифікації дозволяються перейменуванням однією з версій файлу. Таким чином ми можемо гарантувати збереження даних і даємо можливість після завершення синхронізації самому користувачеві вирішити, яке з змін більше йому підходить в кожному конкретному випадку.

Операції синхронізації повинні підкорятися строгому порядку , не можна передавати файл , поки не створена його батьківська директорія . Так само директорію не можна видаляти , поки всередині неї залишаються файли , які потрібно перемістити на нове місце. Алгоритм порівняння дерев вже створює операції в потрібному порядку , але при виникненні помилок він може порушитися . Для запобігання цій ситуації у кожній операції є список залежностей - набір операцій , які повинні завершитися до початку її виконання , і набір операцій , які не повинні початися , поки вона не буде виконана .

Крім залежностей на порядок виконання операцій впливає її пріоритет . Наприклад , операції передачі файлів виконуються в залежності від розмірів файлів - від маленьких до великих .

Всі ці завдання виконуються одночасно , накладаючи додаткові вимоги на якість синхронізації паралельних процесів і розподіл ресурсів всередині ядра синхронізації Яндекс.Диск. Якщо у вас ще немає Я.Диска , завести його можна тут, а встановити для Linux - тут: repo.yandex.ru/yandex-disk .



Comments

comments powered by Disqus