📜 ⬆️ ⬇️

Dropbox style sync on your own server

With this topic, I would like to start a file synchronization dialog. On Habré there were already topics and about Dropbox and about alternative services ( one , two ). The services are excellent, but I was interested in the question: how can I organize file synchronization on my own hardware? I began to look for a ready-made program, but found a little. It seems that most people just call rsync / unison from cron. Writing a client – ​​server program that would track changes to files in a folder seemed simple, and I decided to try it.

I decided to write using Qt. Firstly, a rich set of classes, secondly, support for different platforms, and thirdly - the presence of the QFileSystemWatcher class. With this class, you can receive notifications of changes in the directory. And as the "engine" of synchronization was chosen unison. In fact, the entire application is just a superstructure above the unison utility.

Server


The server part manages users and clients. The client is a specific user's computer. For example, there is a user Vasya, and he has two computers. These two computers will be customers. Clients differ based on hostname. For authorization, I use only the username. Registration of clients occurs automatically if the connecting client has transferred the existing user name (I am going to add password authorization later). Information about users and clients is stored in SQLITE database.

Customer


The main purpose of the client side is to start the synchronization process due to changes in the observed directory. After synchronization, the client asks the server to notify all other clients about the need for synchronization. Clients connected to the server immediately receive a notification, and those not connected will receive it the next time they connect.
')
Since my main working machine is running Windows, I started the experiments with the client part in this system. And here one feature of Qt was found. The QFileSystemWatcher class is a bit strange, in my opinion, it keeps track of directories. Firstly, notifications about changes in subdirectories are not supported, and secondly, if the change happens to the contents of a file, then the same will not be reported. I started to understand the implementation of the QFileSystemWatcher class, it uses the FindFirstChangeNotification function:
HANDLE WINAPI FindFirstChangeNotification(
__in LPCTSTR lpPathName,
__in BOOL bWatchSubtree,
__in DWORD dwNotifyFilter
);

It is immediately evident that it supports monitoring the directory tree. Of course, Qt calls this function with a FALSE value for the bWatchSubtree parameter. The last parameter was also changed by me to be notified of changes in the contents of files. It was:
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);
, it became:
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);

And what about other systems? In Linux, Qt uses either Inotify or Dnotify. They notify about changes to the contents of the file within the directory, but also do not work with subdirectories. It is necessary to monitor each directory separately. The reason why I used to study the implementation of the QFileSystemWatcher class is because I didn’t want to monitor every directory in the directory tree. But this is a topic for discussion and it will be interesting for me to hear Habrovchan’s views on this matter.

I did not understand the details of the QFileSystemWatcher implementation under Mac OS X anymore. Left using the original class. So as a result, under Windows, I use a modified version of the class, and under all other systems - the original one.

results



The result is two programs, Easysync-server and Easysync-client. I tested the server under Ubuntu, and I checked the work of the client part under Windows, Ubuntu and Mac OS X. Under Mac I could not install the version of Unison I needed in the console. If this is done, the client will work under the Mac.

The source code is laid out on Github https://github.com/fralik/Easysync under the GPL license. There are more detailed instructions in English. on installing programs. If you specifically, Habrochelovek, want the instructions to be in Russian, then you can a) translate them or b) send me a personal message. With the accumulation of such messages, I promise to do the translation.

Source: https://habr.com/ru/post/116215/


All Articles