独自のサーバーでのDropboxスタイルの同期

このトピックでは、ファイルの同期についての対話を開始したいと思います。 Habréには、 Dropboxと代替サービス( onetwo )に関するトピックがすでにありました。 サービスは優れていますが、私は質問に興味がありました。自分のハードウェアでファイル同期を整理するにはどうすればよいですか? 既製のプログラムを探し始めましたが、ほとんど見つかりませんでした。 ほとんどの人は、cronからrsync / unisonを呼び出すだけです。 フォルダー内のファイルへの変更を追跡するクライアントサーバープログラムを書くのは簡単に思えたので、試してみることにしました。



私はQtを使用して書くことにしました。 第一に、豊富なクラスのセット、第二に異なるプラットフォームのサポート、第三にQFileSystemWatcherクラスの存在。 このクラスを使用して、ディレクトリの変更の通知を受信できます。 また、ユニゾンが同期の「エンジン」として選択されました。 実際、アプリケーション全体は、ユニゾンユーティリティの単なるアドオンです。



サーバー



サーバー側は、ユーザーとクライアントを管理します。 クライアントは特定のユーザーコンピューターです。 たとえば、ユーザーVasyaがいて、彼には2台のコンピューターがあります。 これら2台のコンピューターが顧客になります。 クライアントはホスト名によって異なります。 認証には、ユーザー名のみを使用します。 接続されたクライアントが既存のユーザー名を転送した場合、クライアントの登録は自動的に行われます(後でパスワード認証を追加します)。 ユーザーとクライアントに関する情報は、SQLITEデータベースに保存されます。



お客様



クライアント部分の主な目的は、監視対象ディレクトリの変更により同期プロセスを開始することです。 同期後、クライアントは、同期の必要性について他のすべてのクライアントに通知するようサーバーに要求します。 サーバーに接続しているクライアントはすぐに通知を受け取りますが、接続していないクライアントは次に接続したときに通知を受け取ります。



私が持っている主な作業マシンはWindowsを実行しているため、このシステムのクライアント部分で実験を開始しました。 そして、Qtの1つの機能が発見されました。 QFileSystemWatcherクラスは少し奇妙ですが、私の意見では、ディレクトリを追跡しています。 第1に、サブディレクトリの変更に関する通知はサポートされていません。第2に、ファイルの内容で変更が発生した場合、それについては何も報告されません。 QFileSystemWatcherクラスの実装を理解し始めました。FindFirstChangeNotification関数を使用します。

HANDLE WINAPI FindFirstChangeNotification(

__in LPCTSTR lpPathName,

__in BOOL bWatchSubtree,

__in DWORD dwNotifyFilter

);







ディレクトリツリーの監視をサポートしていることがすぐにわかります。 もちろん、QtはbWatchSubtreeパラメーターにFALSE値を指定してこの関数を呼び出します。 ファイルの内容の変更に関する通知を受け取るために、最後のパラメーターも変更されました。 それは:

const uint flags = isDir

? (FILE_NOTIFY_CHANGE_DIR_NAME

| FILE_NOTIFY_CHANGE_FILE_NAME)

: (FILE_NOTIFY_CHANGE_DIR_NAME

| FILE_NOTIFY_CHANGE_FILE_NAME

| FILE_NOTIFY_CHANGE_ATTRIBUTES

| FILE_NOTIFY_CHANGE_SIZE

| FILE_NOTIFY_CHANGE_LAST_WRITE

| FILE_NOTIFY_CHANGE_SECURITY);





になりました:

const uint flags = isDir

? (FILE_NOTIFY_CHANGE_DIR_NAME

| FILE_NOTIFY_CHANGE_FILE_NAME

| FILE_NOTIFY_CHANGE_SIZE)

: (FILE_NOTIFY_CHANGE_DIR_NAME

| FILE_NOTIFY_CHANGE_FILE_NAME

| FILE_NOTIFY_CHANGE_ATTRIBUTES

| FILE_NOTIFY_CHANGE_SIZE

| FILE_NOTIFY_CHANGE_LAST_WRITE

| FILE_NOTIFY_CHANGE_SECURITY);







そして、他のシステムはどうですか? Linuxでは、QtはInotifyまたはDnotifyを使用します。 ディレクトリ内のファイルの内容の変更について通知しますが、サブディレクトリでは機能しません。 各ディレクトリを個別に監視する必要があります。 QFileSystemWatcherクラスの実装を勉強するようになったのは、ディレクトリツリー内のすべてのディレクトリを追跡したくないからです。 しかし、これは議論のトピックであり、この点でKhabrovchanの考えを聞くのは興味深いでしょう。



Mac OS XでのQFileSystemWatcherの実装の詳細を理解していませんでした。 元のクラスを使用して残しました。 その結果、Windowsではクラスの修正バージョンを使用し、他のすべてのシステムでは元のシステムを使用します。



結果





その結果、2つのEasysync-serverプログラムとEasysync-clientプログラムが作成されます。 サーバーをUbuntuでテストし、Windows、Ubuntu、Mac OS Xでクライアントパーツの動作を確認しました。Macでは、必要なUnisonのコンソールバージョンをインストールできませんでした。 これが完了すると、クライアントはMacで動作します。



ソースコードはGithub https://github.com/fralik/EasysyncのGPLで入手できます。 英語でより詳細な指示があります。 プログラムをインストールします。 特に、Habrochelovekがロシア語での指示を希望する場合は、a)それらを翻訳するか、b)私に個人的なメッセージを送ってください。 このようなメッセージが蓄積されると、翻訳を行うことを約束します。



All Articles