Задание выполняется на ПК с ОС Linux. Опционально (по желанию) вы можете реализовать вторую часть тестового задания, эта часть должна работать на ПК с ОС Windows 10 Pro.
Ваше ПО разделено на три серивиса: Alfa, Beta и Omega. Сервис Omega имеет UI (описание UI после описания логики). Сервис Omega может запускать/останавливать LXC-контейнер, в котором расположены: — сервис Alfa; — сервис Beta; — браузер Google Chrome.
Обратить внимание: сам сервис Omega работает снаружи LXC-контейнера.
Сервис Omega может запускать и останавливать сервисы Alfa и Beta внутри контейнера, а также обмениваться с ними данными.
IPC реализуется с помощью Unix Domain Socket.
По команде от сервиса Omega сервис Alfa запускает Google Chrome.
С этого момента Alfa начинает перехватывать все системные запросы от Google Chrome на чтение/запись на жёсткий диск.
Alfa в режиме реального времени передаёт в Omega следующие данные по каждому запросу чтения:
— порядковый номер запроса (начинаем с 1);
— длительность операции чтения (в микросекундах);
— размер блока (в байтах);
— время с момента перехвата первого запроса (в микросекундах);
— глубину очереди Queue Depth, в которой находится данная операция чтения;
— опционально для ssd nvme: значение NSSQ в данный момент времени.
Alfa в режиме реального времени передаёт в Omega следующие данные по каждому запросу записи:
— порядковый номер запроса (начинаем с 1);
— длительность операции записи (в микросекундах);
— размер блока (в байтах);
— время с момента перехвата первого запроса (в микросекундах);
— глубину очереди Queue Depth, в которой находится данная операция записи;
— опционально для ssd nvme: значение NSSQ в данный момент времени.
Если сервис Beta запущен, то он в непрерывном режиме сканирует все разделы, использующиеся браузером Google Chrome с частотой T раз в секунду. По умолчанию Т = 1 секунда.
По результатам сканирования Beta передаёт сервису Omega следующие данные:
— список созданных новых файлов по сравнению с первым сканированием;
— список ранее существующих файлов, размер которых изменился по сравнению с первым сканированием;
— время в миллисекундах, потраченное на сканирование.
В списке файлов по каждому файлу передаётся: адреса и название с расширением, размер в байтах.
При первом сканировании передаётся список вообще всех файлов.
Сервис Omega получает данные от Alfa и Beta, проводит их обработку и выводит результаты в UI в режиме реального времени.
Опционально (если вы делаете 2-ую часть задания):
Также эти данные передаются устройству Б по протоколу WebSocket (подробнее об этом в описании утсройтсва Б).
Под "режимом реального времени" понимается так быстро, как возможно, с сохранением корректной очерёдности, то есть, порядок вывода данных в UI должен совпадать с порядком получения этих данных от Alfa и Beta.
Кнопки управления:
— запуск/остановка lxc-контейнера с сервисами;
— запуск/остановка сервиса Alfa;
— запуск/остановка сервиса Beta;
— запуск/закрытие приложения Google Chrome;
— обнулить блоки чтения и записи;
— обнулить блок сканирования;
— опционально: запуск/остановка передачи данных на устройство Б.
Настройки параметров:
— параметр T, размерность "раз в секунду";
— параметр M, размерность "миллисекунды".
Блок "Чтение":
Выводит операции чтения строго в той же очерёдности, как они были получены при перехвате сервисом Alfa, причём первая операция будет находиться внизу списка, а последняя — вверху списка, то есть, список растёт вверх.
Если с момента последней операции чтения прошло более M миллисекунд (по умолчанию М = 500), то выводим строку синего цвета с надписью "Итоги:" и следующими значениями:
— сколько времени в микросекундах прошло с момента перехвата первого запроса чтения до момента завершения последнего запроса чтения;
— сколько операций чтения выполнено за этот период;
— какой суммарный размер блоков байтах прочитан за этот период;
— фактическая частота операций чтения = количество операций / период, результат считаем в количестве операций в секунду;
— фактическая скорость чтения = суммарный размер блоков в байтах / период, результат считаем в мегабайтах в секунду;
— максимальное значение среди значений Queue Depth;
— опционально: максимальное значение среди значений NSSQ.
Блок "Запись":
Полностью аналогичен блоку "Чтение", только выводит значения по операциям записи.
Блок "Сканирование":
Выводит список всех файлов Google Chrome.
— Сверху под заголовком "Новые:" зелёным цветом выводятся новые файлы.
— Далее под заголовком "Последние изменения:" голубым цветом выводятся файлы, размер которых изменился по сравнению в с прошлым сканированием и величина изменения в байтах.
— Далее под заголовком "Изменены с начала" фиолетовым цветом выводятся файлы, которые не менялись с момента последнего сканирования, но изменялись с момента их первого появления. К таким файлам указывается итоговая разница их размера по сравнению с начальным значением.
— Далее красным выводятся файлы, удаление которых было обнаружено на хотя бы одном из сканов.
— Далее чёрным выводятся файлы, которые ни разу не менялись по сравнению с первым сканом.
Поверх этих списков файлов выводятся суммарные значения:
— изначальное количество файлов и их размер;
— сколько новых файлов было создано за всё время (начиная со второго сканирования);
— у скольких файлов изменился размер за всё время (начиная со второго сканирования);
— сколько файлов было удалено за всё время (начиная со второго сканирования);
— сколько байт было записано суммарно за всё время (начиная со второго сканирования).
Блок "Сравнение" выводит:
— Суммарное количество байт записи полученное с помощью сервиса Alfa.
— Суммарное количество байт записи полученное с помощью сервиса Beta.
— Разницу между этими значениями.
Реализуйте для устройства Б отдельный UI, который будет принимать от устройста А данные по протоколу WebSocket и выводить эти данные в таких же блоках "Чтение", "Запись", "Сканирование" и "Сравнение".
Одновременно с этим все данные записываются в БД PostgreSQL.
В UI должны быть дополнительно предусмотрены два режима просмотра: RealTime и Dump.
В режиме RealTime мы видим обновление данных, прилетающих с устройства А в режиме реального времени.
В режиме Dump приём данных прекращается и мы видим все данные записанные в базу.
В UI также предусмотрена кнопка Delete Dump, которая очищает базу данных.
— Для решения высокоуровневых задач вы можете использовать Java или Kotlin на своё усмотрение.
— Для решения низкоуровневых задач безальтернативно использование С/C++.
- Понимание модульности в проекте (в нашем случае это несколько приложений в рамках единого проекта).
- Применение шаблона проектирования Singleton.
- Умение рефакторить собственный код (покажите оптимальные чистые решения без мусора).
- Использование DI решений.
- Отсутствие закомментированного кода (в смысле мусора).
- Наличие кратких содержательных комментариев к коду (защита кода будет на собеседовании)
- Разделение сервисов на слои.