summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorАндрей Гущин <saintruler@gmail.com>2019-06-06 10:02:41 +0300
committerАндрей Гущин <saintruler@gmail.com>2019-06-06 10:02:41 +0300
commit3cfb10729201b806b09a12de4eef6abb3b71aad5 (patch)
tree06d5fd4b269d40dc0c5863e6c419cb95144db560
parent5191aa270d852da42ff8adbd630daeb7fb82fa23 (diff)
parent4a3db50d7df0f636ef824637d33330543e9044b2 (diff)
Merge branch 'day4_task3' into 'master'HEADmaster
День 4, задача 3 See merge request saintruler/trainee!18
-rw-r--r--day4/task3/client.py85
-rw-r--r--day4/task3/db.py73
-rw-r--r--day4/task3/server.py100
3 files changed, 258 insertions, 0 deletions
diff --git a/day4/task3/client.py b/day4/task3/client.py
new file mode 100644
index 0000000..18bb2b1
--- /dev/null
+++ b/day4/task3/client.py
@@ -0,0 +1,85 @@
+import socket
+from time import sleep
+import struct
+import json
+
+
+HOST, PORT = ADDR = 'localhost', 6000
+DATATYPE_SIZE = 4 # int
+
+
+def pack_data(data):
+ encoded = data.encode()
+ return struct.pack('I', len(encoded)) + encoded
+
+
+def get_data(connection):
+ buffer = b''
+ # Считываем размер пакета
+ while len(buffer) < DATATYPE_SIZE:
+ data = connection.recv(DATATYPE_SIZE - len(buffer))
+ if not data:
+ raise ConnectionError('Connection was closed')
+
+ buffer += data
+
+ size_packed, buffer = buffer[:DATATYPE_SIZE], buffer[DATATYPE_SIZE:]
+ if not size_packed:
+ raise ConnectionError('Connection was closed')
+
+ (size,) = struct.unpack('I', size_packed)
+ data = connection.recv(size - len(buffer))
+ return buffer + data
+
+
+def parse_data(data):
+ return json.loads(data.decode())
+
+
+def try_connect():
+ cnt = 0
+ sock = socket.socket()
+ while cnt < 10:
+ try:
+ cnt += 1
+ sock.connect(ADDR)
+
+ except ConnectionRefusedError:
+ print('Не удалось подключиться к серверу. Следующая попытка через 3 секунды...')
+ sleep(3)
+
+ else:
+ return sock
+
+ else:
+ print('Не удалось подключиться к серверу через 10 попыток.\nОстанавливаемся...')
+ sock.close()
+ return
+
+
+def main():
+ sock = try_connect()
+ if sock is None:
+ quit()
+
+ while True:
+ try:
+ data = input('Введите модуль для поиска:\n')
+
+ except KeyboardInterrupt:
+ break
+
+ else:
+ sock.sendall(pack_data(data))
+ response = get_data(sock)
+ arr = parse_data(response)
+
+ print(f'Найдено {len(arr)} совпадений:')
+ for line in arr:
+ print(line)
+
+ sock.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/day4/task3/db.py b/day4/task3/db.py
new file mode 100644
index 0000000..c23e9fb
--- /dev/null
+++ b/day4/task3/db.py
@@ -0,0 +1,73 @@
+import re
+import bisect
+from datetime import datetime
+
+
+db = []
+
+
+def search_by_date(hour, minute=None, second=None, data=None):
+ low = [hour]
+ high = [hour]
+ if minute is not None:
+ low.append(minute)
+ high.append(minute)
+
+ if second is not None:
+ low.append(second)
+ high.append(second + 1)
+ else:
+ high.append(60)
+ else:
+ high.append(60)
+
+ left = bisect.bisect_left(db, tuple(low))
+ right = bisect.bisect_left(db, tuple(high))
+ return [t[4] for t in db[left:right] if data in t[3]]
+
+
+def open_log(path):
+ try:
+ f = open(path)
+
+ except FileNotFoundError:
+ print('Файл с логом не обнаружен')
+ return
+
+ except PermissionError:
+ print('Файл с логом не доступен для чтения')
+ return
+
+ return f
+
+
+# Возвращает значение успешности инициализации базы данных
+def init(path) -> bool:
+ f = open_log(path)
+ if f is None:
+ return False
+
+ matcher = re.compile(r'\[(?P<date>.*?)\]\[(?P<type>.*?)\]\[(?P<module>.*?)\]\[(?P<id>.*?)\] (?P<text>.*)')
+
+ lines = f.readlines()
+ f.close()
+ for line in lines:
+ line = line.strip()
+ match = re.match(matcher, line)
+
+ if match:
+ try:
+ date = datetime.strptime(match.group('date'), '%c')
+ except ValueError:
+ print(f'Ошибка при разборе строки (Неверный формат даты):\n{line}')
+ continue
+
+ module = match.group('module')
+
+ db.append((date.hour, date.minute, date.second, module, line))
+
+ else:
+ print(f'Ошибка при разборе строки:\n{line}')
+
+ db.sort()
+ return True
diff --git a/day4/task3/server.py b/day4/task3/server.py
new file mode 100644
index 0000000..3aea050
--- /dev/null
+++ b/day4/task3/server.py
@@ -0,0 +1,100 @@
+import socket
+import struct
+from db import search_by_date
+import re
+import json
+import time
+
+
+HOST, PORT = ADDR = '0.0.0.0', 6000
+DATATYPE_SIZE = 4 # int
+
+
+def pack_data(data):
+ encoded = data.encode()
+ return struct.pack('I', len(encoded)) + encoded
+
+
+def handle_request(data):
+ match = re.match(r'(\d+):?(\d+)?:?(\d+)?-(.*)', data)
+ if match:
+ *date, msg = match.groups()
+
+ t = time.time()
+ found = search_by_date(*map(lambda i: int(i) if i is not None else i, date), msg)
+ print(f'Search took {time.time() - t} seconds')
+ return pack_data(json.dumps(found))
+
+ else:
+ print('String not matched.')
+ return pack_data(json.dumps([]))
+
+
+def get_data(connection):
+ buffer = b''
+ # Считываем размер пакета
+ while len(buffer) < DATATYPE_SIZE:
+ data = connection.recv(DATATYPE_SIZE - len(buffer))
+ if not data:
+ raise ConnectionError('Connection was closed')
+
+ buffer += data
+
+ size_packed, buffer = buffer[:DATATYPE_SIZE], buffer[DATATYPE_SIZE:]
+ if not size_packed:
+ raise ConnectionError('Connection was closed')
+
+ (size,) = struct.unpack('I', size_packed)
+ data = connection.recv(size - len(buffer))
+ return buffer + data
+
+
+def handle_connection(connection, address):
+ while True:
+ try:
+ data = get_data(connection)
+
+ except ConnectionResetError:
+ print(f'Connection with {address[0]} was unexpectedly closed')
+ break
+
+ except ConnectionError:
+ print(f'Connection with {address[0]} was ended')
+ break
+
+ except KeyboardInterrupt:
+ raise KeyboardInterrupt()
+
+ else:
+ if not data:
+ print(f'Connection with {address[0]} was ended')
+ break
+ response = handle_request(data.decode())
+ connection.sendall(response)
+
+
+def main():
+ sock = socket.socket()
+ sock.bind(ADDR)
+ sock.listen(5)
+
+ while True:
+ print('Listening for new connections...')
+ try:
+ connection, address = sock.accept()
+ print(f'Got a connection from {address[0]}')
+ handle_connection(connection, address)
+
+ except KeyboardInterrupt:
+ print('Stopping server...')
+ sock.close()
+ print('Server stopped')
+ break
+
+
+if __name__ == '__main__':
+ success = db.init('otrs_error.log')
+ if not success:
+ print('Не удалось инициализировать базу данных. Завершаем работу...')
+ else:
+ main()