|
|
|
from services.server_service import ServerMessage, ServerService
|
|
|
|
|
|
|
|
import json
|
|
|
|
import asyncio
|
|
|
|
|
|
|
|
"""
|
|
|
|
This is how you can save a file:
|
|
|
|
|
|
|
|
async def test_file_save():
|
|
|
|
async with data_service.open('filename') as f:
|
|
|
|
print('write content')
|
|
|
|
await f.write('test string')
|
|
|
|
|
|
|
|
async with data_service.open('filename') as f:
|
|
|
|
content = await f.load()
|
|
|
|
print(content)
|
|
|
|
print('test file ok')
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
LOCK_WAIT_SLEEP_TIMESPAN = 100 # mc
|
|
|
|
|
|
|
|
class FileDescriptor:
|
|
|
|
def __init__(self, filename: str, data_service):
|
|
|
|
self.filename = filename
|
|
|
|
self.data_service = data_service
|
|
|
|
|
|
|
|
async def write(self, content: str):
|
|
|
|
await self.data_service.save_file_content(self, content)
|
|
|
|
|
|
|
|
async def load(self) -> str:
|
|
|
|
return await self.data_service.load_file_content(self)
|
|
|
|
|
|
|
|
async def __aenter__(self):
|
|
|
|
await self.data_service.wait_and_lock(self)
|
|
|
|
return self
|
|
|
|
|
|
|
|
async def __aexit__(self, *exc):
|
|
|
|
await self.data_service.unlock(self)
|
|
|
|
|
|
|
|
|
|
|
|
class DataService:
|
|
|
|
|
|
|
|
def __init__(self, server_service: ServerService):
|
|
|
|
"""Creates fs over network via server_service"""
|
|
|
|
self.server_service = server_service
|
|
|
|
self.locks = set()
|
|
|
|
|
|
|
|
def open(self, filename: str) -> FileDescriptor:
|
|
|
|
return FileDescriptor(filename, self)
|
|
|
|
|
|
|
|
async def wait_and_lock(self, file_descriptor: FileDescriptor):
|
|
|
|
filename = file_descriptor.filename
|
|
|
|
while True:
|
|
|
|
if filename in self.locks:
|
|
|
|
asyncio.sleep(LOCK_WAIT_SLEEP_TIMESPAN)
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
self.locks.add(filename)
|
|
|
|
break
|
|
|
|
|
|
|
|
async def unlock(self, file_descriptor: FileDescriptor):
|
|
|
|
filename = file_descriptor.filename
|
|
|
|
self.locks.remove(filename)
|
|
|
|
|
|
|
|
async def save_file_content(self, file_descriptor: FileDescriptor, content: str):
|
|
|
|
""" Saves json - serializable obj with file_descriptor.filename """
|
|
|
|
self.__check_lock(file_descriptor)
|
|
|
|
message_payload = {
|
|
|
|
'filename': file_descriptor.filename,
|
|
|
|
'content': content
|
|
|
|
}
|
|
|
|
message = ServerMessage('FILE_SAVE', message_payload)
|
|
|
|
await self.server_service.send_request(message)
|
|
|
|
|
|
|
|
async def load_file_content(self, file_descriptor: FileDescriptor) -> str:
|
|
|
|
self.__check_lock(file_descriptor)
|
|
|
|
message_payload = { 'filename': file_descriptor.filename }
|
|
|
|
message = ServerMessage('FILE_LOAD', message_payload)
|
|
|
|
return await self.server_service.send_request(message)
|
|
|
|
|
|
|
|
def __check_lock(self, file_descriptor: FileDescriptor):
|
|
|
|
filename = file_descriptor.filename
|
|
|
|
if filename not in self.locks:
|
|
|
|
raise RuntimeError('No lock for file %s' % filename)
|