forked from CPP-Final-Project/Chat_Server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLocalStorage_Service.cpp
More file actions
333 lines (293 loc) · 11 KB
/
LocalStorage_Service.cpp
File metadata and controls
333 lines (293 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
#include "LocalStorage_Service.h"
QSharedPointer<LocalStorage_Service> LocalStorage_Service::shp_instance = nullptr;
QMutex LocalStorage_Service::mutex;
QSharedPointer<LocalStorage_Service> LocalStorage_Service::getInstance(const int minutes_)
{
try
{
if (!shp_instance)
{
QMutexLocker locker(&mutex);
if (!shp_instance)
{
shp_instance = QSharedPointer<LocalStorage_Service>(new LocalStorage_Service(), &QObject::deleteLater);
connect(shp_instance.get(), &close, shp_instance.get(), &safeExit);
}
}
return shp_instance;
}
catch (const QException& ex)
{
PLOGE << "Error occurred while creating instance of localStorage: " << ex.what();
}
return nullptr;
}
LocalStorage_Service::LocalStorage_Service(QObject* object_) : QObject(object_) {}
bool LocalStorage_Service::addLikeToMessage(const quint32& room_id_, const QUuid& message_id_, const QDateTime& message_datetime_, const QString& user_login_, const bool like_dislike_)
{
try
{
const auto file = searchForFiles(message_datetime_, room_id_);
auto db_messages = readMessagesFromDB("rooms/" + QString::number(room_id_) + file);
if (!db_messages.empty())
{
foreach(auto & message, db_messages)
{
if (message->getId() == message_id_)
{
message->addLike(user_login_, like_dislike_);
break;
}
}
QJsonArray array;
for (const auto& message : db_messages) {
array.append(message->toJson());
}
FileRepository::writeJsonArr("rooms/" + QString::number(room_id_) + file, array, true);
return true;
}
return false;
}
catch (const QException& ex)
{
PLOGE << "Error occurred while adding message to local storage: " << ex.what();
return false;
}
}
QSet<QSharedPointer<DBEntity::DBMessage>> LocalStorage_Service::readMessagesFromDB(const QString& file_name_)
{
QJsonArray array;
FileRepository::readJsonArr(file_name_, array);
QSet<QSharedPointer<DBEntity::DBMessage>> messages;
for (const auto obj : array) {
if (obj.isObject())
{
QJsonObject json_object = obj.toObject();
QSharedPointer<DBEntity::DBMessage> message(new DBEntity::DBMessage());
message->fromJson(json_object);
messages.insert(message);
}
else
{
PLOGE << "File is corrupted";
}
}
return messages;
}
QList<QString> LocalStorage_Service::searchForFiles(const QDateTime& from_, const QDateTime& to_, const quint32& room_) const
{
QList<QString> file_names;
QDir directory("rooms/" + QString::number(room_));
QStringList all_files = directory.entryList(QDir::Files);
bool is_empty = true;
const QRegularExpression regex(R"(((\d{8}_\d{4})&(\d{8}_\d{4}))\.json)");
for (const QString& file_name : all_files)
{
if (QRegularExpressionMatch match = regex.match(file_name); match.hasMatch())
{
QString earliest_date = match.captured(2);
QString latest_date = match.captured(3);
QDateTime from = QDateTime::fromString(earliest_date, "yyyyMMdd_hhmm");
QDateTime to = QDateTime::fromString(latest_date, "yyyyMMdd_hhmm");
if ( from >= from_ || to <= to_)
{
file_names.append(file_name);
is_empty = false;
}
}
}
if (is_empty)
{
PLOGW << "No messages for this date was retrieved from database";
}
return file_names;
}
QString LocalStorage_Service::searchForFiles(const QDateTime& date_, const quint32& room_) const
{
QString file_names_res;
QDir directory("rooms/" + QString::number(room_));
QStringList all_files = directory.entryList(QDir::Files);
bool is_empty = true;
const QRegularExpression regex(R"(((\d{8}_\d{4})&(\d{8}_\d{4}))\.json)");
for (const QString& file_name : all_files)
{
if (QRegularExpressionMatch match = regex.match(file_name); match.hasMatch())
{
QString earliest_date = match.captured(2);
QString latest_date = match.captured(3);
QDateTime from = QDateTime::fromString(earliest_date, "yyyyMMdd_hhmm");
QDateTime to = QDateTime::fromString(latest_date, "yyyyMMdd_hhmm");
if (from <= date_ && to >= date_)
{
return file_name;
}
}
}
if (is_empty)
{
PLOGW << "No messages for this date was retrieved from database";
}
return "";
}
QString LocalStorage_Service::searchForFiles(const QDateTime& date_, const quint32& room_, const bool& from_to_) const
{
QDir directory("rooms/" + QString::number(room_));
QStringList all_files = directory.entryList(QDir::Files);
bool is_empty = true;
const QRegularExpression regex(R"(((\d{8}_\d{4})&(\d{8}_\d{4}))\.json)");
for (const QString& file_name : all_files)
{
if (QRegularExpressionMatch match = regex.match(file_name); match.hasMatch())
{
QString earliest_date = match.captured(2);
QString latest_date = match.captured(3);
QDateTime from = QDateTime::fromString(earliest_date, "yyyyMMdd_hhmm");
QDateTime to = QDateTime::fromString(latest_date, "yyyyMMdd_hhmm");
if(from_to_)
{
if (to >= date_)
{
return file_name;
}
}
else
{
if(from <= date_)
{
return file_name;
}
}
}
}
if (is_empty)
{
PLOGW << "No messages for this date was retrieved from database";
}
return "";
}
void LocalStorage_Service::addMessage(const QSharedPointer<User_Message>& shp_message_, const quint32 room_id_)
{
try
{
if (message_storage.contains(room_id_))
{
message_storage[room_id_].insert(DTOModel::DTOMessage::createDBFromSrv(shp_message_));
PLOGI << "Message saved in local storage";
}
else
{
message_storage.insert(room_id_, QSet{ DTOModel::DTOMessage::createDBFromSrv(shp_message_) });
PLOGI << "Message saved in local storage";
}
}
catch (const QException& ex)
{
PLOGE << "Error occurred while adding message to local storage: " << ex.what();
}
}
QSet<QSharedPointer<User_Message>> LocalStorage_Service::getMessages(const QDateTime& from_, const QDateTime& to_, const quint32& room_id_)
{
QSet<QSharedPointer<User_Message>> result;
QtConcurrent::map(message_storage.value(room_id_), [&result, &from_, &to_](QSharedPointer<DBEntity::DBMessage> message) {
if (auto date = message->getDateTime(); date >= from_ && date <= to_)
{
result.insert(DTOModel::DTOMessage::createSrvFromDB(message));
}
}).waitForFinished();
return result;
}
QSet<QSharedPointer<User_Message>> LocalStorage_Service::getMessages(const quint32& room_id_, const QDateTime& time_, bool from_to_, const quint32& pool_size_)
{
QList<QSharedPointer<DBEntity::DBMessage>> temp_messages;
QSet<QSharedPointer<User_Message>> result;
QtConcurrent::map(message_storage.value(room_id_), [&temp_messages, &time_, &from_to_, &pool_size_](QSharedPointer<DBEntity::DBMessage> message) {
if (from_to_) {
if (auto date = message->getDateTime(); date > time_)
{
temp_messages.append(message);
}
}
else {
if (auto date = message->getDateTime(); date < time_)
{
temp_messages.append(message);
}
}
}).waitForFinished();
std::sort(temp_messages.begin(), temp_messages.end(), [](const QSharedPointer<DBEntity::DBMessage>& a, const QSharedPointer<DBEntity::DBMessage>& b) {
return a->getDateTime() > b->getDateTime();
});
if (!temp_messages.empty()) {
int j = 0;
for (QList<QSharedPointer<DBEntity::DBMessage>>::iterator i = temp_messages.begin(); i != temp_messages.end() || j < pool_size_; i++)
{
j++;
result.insert(DTOModel::DTOMessage::createSrvFromDB(*i));
}
}
return result;
}
void LocalStorage_Service::saveAllMessages()
{
try {
if (!shp_instance->message_storage.empty())
{
QMutexLocker locker(&mutex);
auto keys = shp_instance->message_storage.keys();
QtConcurrent::blockingMap(keys, [this](const quint32 key_) {
auto list = QList(message_storage[key_].begin(), message_storage[key_].end());
std::sort(list.begin(), list.end(), [](const QSharedPointer<DBEntity::DBMessage>& a,
const QSharedPointer<DBEntity::DBMessage>& b)
{
return a->getDateTime() > b ->getDateTime();
});
QString earliest_time = list.first()->getDateTime().toString("yyyyMMdd_hhmm");
QString latest_time = list.last()->getDateTime().toString("yyyyMMdd_hhmm");
QString file_name = "rooms/" + QString::number(key_) + "/" + earliest_time +"&" + latest_time + ".json";
QDir().mkpath("rooms/" + QString::number(key_));
QJsonArray array;
for (const auto& message : list) {
array.append(message->toJson());
}
if (!FileRepository::writeJsonArr(file_name, array)) {
PLOGE << "Error writing to file";
}
PLOGI << "Writing messages successfully";
shp_instance->message_storage.remove(key_);
});
}
else PLOGI << "message_storage is empty.";
}
catch(const QException& ex)
{
PLOGE << "Error occurred while saving all messages to file system: " << ex.what();
}
}
void LocalStorage_Service::safeExit()
{
saveAllMessages();
shp_instance->deleteLater();
PLOGI << "Local storage service safely closed";
}
void LocalStorage_Service::addMessages(const QSet<QSharedPointer<User_Message>>& messages_, const quint32 room_id_) {
try
{
if (!message_storage.contains(room_id_)) {
QSet<QSharedPointer<DBEntity::DBMessage>> new_room_history;
message_storage.insert(room_id_, new_room_history);
PLOGI << "Added messages to local storage";
}
else
{
foreach(const auto & message, messages_)
{
message_storage.value(room_id_).insert(DTOModel::DTOMessage::createDBFromSrv(message));
}
PLOGI << "Added room with messages to local storage";
}
}
catch (const QException& ex)
{
PLOGE << "Error occurred while saving all messages to storage: " << ex.what();
}
}