Цел на системата
Поддръжка на дистанционен достъп до файлове на компютри в мрежата. Системата „виртуално“ поддържа всички основни файлови операции (създаване, изтриване, четене, запис и др.) чрез обмен на транзакции (съобщения) по протокол TCP.
Области на приложение
Функционалността на системата е ефективна в следните случаи:
- в нативни приложения за мобилни и вградени устройства (смартфони, бордови системи за управление и т.н.), изискващи бърз достъп до файлове на отдалечени сървъри при вероятни времеви прекъсвания на връзката (при излизане офлайн);
- в натоварени СУБД, ако обработката на запитванията се извършва на едни сървъри, а съхранението на данни – на други;
- в разпределени корпоративни мрежи за събиране и обработка на информация, изискващи висока скорост на обмен на данни, резервиране и надеждност;
- в сложни системи с микросервизна архитектура, където забавянията в обмена на информация между модулите имат критично значение.
Структура
Системата Cage (има реализация — бета версия на Python 3.7 в ОС Windows) включва две основни части:
- Cageserver — програма файл-сървър (пакет от функции), която се стартира на компютри в мрежата, до файловете на които е необходим дистанционен достъп;
- клас Cage с библиотека от методи за клиентски софтуер, опростяваща кодирането на взаимодействието със сървърите.
Използване на системата от страна на клиентите
Методите на класа Cage заменят обикновените, „рутинни“ операции на файловата система: създаване, отваряне, затваряне, изтриване на файлове, както и четене/запис на данни в бинарен формат (с указание на позицията и размера на данните). Концептуално тези методи са близки до файловите функции на езика C, където отварянето/затварянето на файлове се извършва „на канали“ за вход и изход.
С други думи, програмистът работи не с методите на „файловите“ обекти (класа _io в Python), а с методите на класа Cage.
При създаването на екземпляр на обект Cage той установява начална връзка със сървера (или няколко сървъра), преминава авторизация по Id на клиента и получава потвърждение с номер на определен порт за извършване на всички файлови операции. При изтриването на обекта Cage, той изпраща команда на сървера за прекратяване на връзката и затваряне на файловете. Прекратяването на връзката може да бъде иницирано и от самите сървъри.
Системата увеличава производителността на четенето/записването, базирана на буферизацията на често използвани части от файлове в кеша (буфера) на оперативната памет.
Клиентският софтуер може да използва неограничен брой обекти Cage с различни настройки (обем на буферната памет, размер на блоковете при обмена с сървъра и др.).
Един обект Cage може да обменя данни с няколко файла на различни сървъри. Параметрите за връзка (IP адрес или DNS на сървъра, основен порт за авторизация, път и име на файла) се задават при създаването на обекта.
Тъй като всеки обект Cage може едновременно да работи с множество файлове, за буферизацията се използва общо пространство в паметта. Размерът на кеша – количеството страници и техният размер, се задава динамично при създаването на обекта Cage. Например, кеш от 1 ГБ е 1000 страници по 1 МБ или 10 000 страници по 100 КБ, или 1 милион страници по 1 КБ. Изборът на размер и количество страници е конкретна задача за всеки практичен случай.
Може да се използват едновременно няколко обекта Cage, за да се зададат различни настройки на буферната памет в зависимост от особеностите на достъпа до информацията в различните файлове. Като основен се прилага най-простият алгоритъм за буферизация: след изчерпването на зададения обем памет новите страници заменят старите на принципа на изтегляне с минимален брой достъпи. Буферизацията е особено ефективна при нееднороден (в статистически смисъл) съвместен достъп, от една страна, до различни файлове и, от друга страна, до фрагменти на всеки файл.
Класът Cage поддържа вход/изход не само по адресите на данни (с указване на позицията и дължината на масива, 'заменяйки' операциите на файловата система), но и на по-ниско, 'физическо' ниво – по номера на страниците в буферната памет.
За обектите Cage се поддържа оригинална функция „хибернация“ («сна») – те могат да бъдат «свити» (например, в случай на прекъсване на връзката с серверите или при спиране на приложението и т.н.) в локален дамп файл на страната на клиента и бързо да бъдат възстановени от този файл (след възстановяване на връзката, при повторно стартиране на приложението). Това позволява съществено намаляване на трафика при активиране на клиентската програма след временно излизане „офлайн“, тъй като често използваните фрагменти от файловете вече ще се намират в кеша.
Cage — това е около 3600 реда код.
Принципи на изграждане на сървъри
Файл-сървърите Cageserver могат да бъдат стартирани с произволен брой портове, един от които („основен“) се използва само за авторизация на всички клиенти, а другите — за обмен на данни. За програмата на сървъра Cage е необходим само Python. Паралелно, компютърът с файл-сървъра може да изпълнява всякаква друга работа.
Сървърът се стартира първо като съвкупност от два основни процеса:
- „Свързвания“ – процес за извършване на операции за установяване на връзка с клиентите и прекратяването й по инициатива на сървъра;
- „Операции“ – процес за извършване на задания (операции) на клиентите за работа с файлове, а също така за затваряне на сесиите на връзка по команди на клиентите.
И двата процеса не са синхронизирани и са организирани като безкрайни цикли за приемане и изпращане на съобщения на базата на многопроцесни опашки, прокси-обекти, заключвания и сокети.
Процесът „Свързвания“ определя на всеки клиент порт за приемане и предаване на данни. Броят на портовете се задава при стартиране на сървъра. Съответствието между портовете и клиентите се съхранява в споделена между процеся прокси-памет.
Процесът „Операции“ поддържа разделяне на файловите ресурси, при което няколко различни клиенти могат съвместно (квазипаралелно, тъй като достъпът се управлява от заключвания) да четат данни от един файл, ако това е било разрешено при първоначалното му отваряне „от първия“ клиент.
Обработката на команди за създаване/изтриване/отваряне/затваряне на файлове на сървър се извършва в самия процес „Операции“ строго последователно с използване на файловата подсистема на ОС на сървъра.
За общото ускорение на четене/писане, тези операции се извършват в потоци (threads), генерирани от процеса "Операции". Броят на потоковете обикновено е равен на броя на отворените файлове. Задачите за четене/писане от клиентите се подават в обща опашка и първият освободен поток поема задачата от нейния връх. Специална логика позволява да се изключат операциите за перезапис на данни в оперативната памет на сървъра.
Процесът "Операции" следи активността на клиентите и прекратява тяхното обслужване както по техни команди, така и при превишаване на таймаута за неактивност.
За осигуряване на надеждност, Cageserver води журнали на всички транзакции. Един общ журнал съдържа копия на съобщения от клиентите с задачи за създаване/отваряне/преименуване/изтриване на файлове. За всеки работен файл се създава отделен журнал, в който се записват копия на съобщения с задачи за четене и запис на данни в този работен файл, както и масиви от записаните (нови) данни и масиви от данни, които са били унищожени при перезапис (записване на нови данни "върху" стари).
Тези журнали осигуряват възможност както за възстановяване на новите изменения в резервните копия, така и за "откат" от текущото съдържание към необходимия момент в миналото.
Cageserver е около 3100 реда код.

Стартиране на програмата файл-сървър Cageserver
При стартиране в диалога трябва да се определи:
— основен порт за авторизация;
— брой портове за обмен на транзакции с авторизирани клиенти (от 1 и повече, пулът номера започва от следващия след основния порт).
Използване на класа Cage
клас cage.Cage( cage_name=", pagesize=0, numpages=0, maxstrlen=0, server_ip={}, wait=0, awake=False, cache_file="" )
От този клас се създават обекти, които осъществяват взаимодействие с файл-сървърите и съдържат буферна памет.
Параметри
- cage_name(str) — условно име на обекта, което се използва при идентификация на клиентите на страната на сървъра
- pagesize(int) — размер на едната страница буферна памет (в байтове)
- numpages(int) — брой страници буферна памет
- maxstrlen(int) — максимална дължина на байтовата низ във операциите по запис и четене
- server_ip(dict) — речник с адресите, използвани сървъри, където ключът е условно име на сървъра (id на сървъра вътре в приложението), а стойността е низ с адрес: “ip address:port” или “DNS:port” (съпоставянето на имената и реалните адреси е временно, може да се променя)
- wait(int) — времето за изчакване за отговор от сървъра при получаване на портовете (в сек.)
- буден(boolean) — флаг на метода за създаване на обект (False — ако се създава нов обект, True — ако обектът се създава от преди „свърнат“ — чрез операцията „хибернация“, по подразбиране False)
- cache_file(str) — името на файла за хибернация
Методите
Кейдж.file_create( сървър, път ) – създава нов файл
Кейдж.file_rename( сървър, път, ново_име ) – преименува файл
Кейдж.file_remove( сървър, път) – изтрива файл
Кейдж.open( сървър, път, мод ) – отваря файл
Връща fchannel номер на канала. Параметър mod — това е режимът на отваряне на файла: „wm“ — монополен (четене/запис), „rs“ — само за четене, и споделен само за четене от други клиенти, „ws“ — четене/запис, и споделен само за четене от други клиенти.
Кейдж.close (fchannel) – затваря файл
Кейдж.write (fchannel, begin, data ) – записва байтова низ в файл
Кейдж.read (fchannel, begin, len_data ) – чете байтова низ от файл
Кейдж.put_pages ( fchannel ) – „изтласква“ от буфера на сървъра всички страници на указан канал, които са били модифицирани. Използва се в онези точки на алгоритъма, където е необходимо да се уверим, че всички операции на канала физически са запазени в файла на сървъра.
Кейдж.push_all () – „изтласква“ от буфера на сървъра всички страници на всички канали за екземпляр на класа Cage, които са били модифицирани. Използва се, когато е необходимо да се уверим, че всички операции на всички канали са запазени на сървъра.
Източник: habr.com
