-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathFileManager.h
427 lines (297 loc) · 11.6 KB
/
FileManager.h
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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#pragma once
/**
SexyOS
FileManager.h
Przeznaczenie: Zawiera klasê FileManager oraz deklaracje metod i konstruktorów
@author Tomasz Kiljañczyk
*/
/*
* Aby ³atwiej nawigowaæ po moim kodzie polecam z³o¿yæ wszystko
* Skrót: CTRL + M + L
*/
#define _CRT_SECURE_NO_WARNINGS
#include "Semaphores.h"
#include <string>
#include <array>
#include <bitset>
#include <vector>
#include <unordered_map>
#include <map>
//Do u¿ywania przy funkcji open (nazwy mówi¹ same za siebie)
#define FILE_OPEN_R_MODE 1 //01
#define FILE_OPEN_W_MODE 2 //10
//Do u¿ycia przy obs³udze b³êdów
#define FILE_ERROR_NONE 0
#define FILE_ERROR_EMPTY_NAME 1
#define FILE_ERROR_NAME_USED 2
#define FILE_ERROR_NO_INODES_LEFT 3
#define FILE_ERROR_DATA_TOO_BIG 4
#define FILE_ERROR_NOT_FOUND 5
#define FILE_ERROR_NOT_OPENED 6
#define FILE_ERROR_OPENED 7
#define FILE_ERROR_SYNC 8
#define FILE_ERROR_NOT_R_MODE 9
#define FILE_ERROR_NOT_W_MODE 10
#define FILE_SYNC_WAITING 30
//Klasa zarz¹dcy przestrzeni¹ dyskow¹ i systemem plików
class FileManager {
private:
//--------------------------- Aliasy ------------------------
using u_int = unsigned int;
using u_short_int = unsigned short int;
//--------------- Definicje sta³ych statycznych -------------
static const uint8_t BLOCK_SIZE = 32; //Rozmiar bloku (bajty)
static const u_short_int DISK_CAPACITY = 1024; //PojemnoϾ dysku (bajty)
static const uint8_t BLOCK_INDEX_NUMBER = 3; //Wartoœæ oznaczaj¹ca d³ugoœæ pola blockDirect
static const uint8_t INODE_NUMBER_LIMIT = 32; //Maksymalna iloœæ elementów w katalogu
static const bool BLOCK_FREE = false; //Wartoœæ oznaczaj¹ca wolny blok
static const bool BLOCK_OCCUPIED = !BLOCK_FREE; //Wartoœæ oznaczaj¹ca zajêty blok
//Maksymalny rozmiar danych
static const u_short_int MAX_DATA_SIZE = (BLOCK_INDEX_NUMBER + BLOCK_SIZE / 2)*BLOCK_SIZE;
//Maksymalny rozmiar pliku (wliczony blok indeksowy)
static const u_short_int MAX_FILE_SIZE = MAX_DATA_SIZE + BLOCK_SIZE;
//---------------- Definicje struktur i klas ----------------
//Klasa i-wêz³a - zawiera podstawowe informacje o pliku
struct Inode {
//Podstawowe informacje
uint8_t blocksOccupied = 0; //Iloœæ zajmowanych bloków
u_short_int realSize = 0; //Rzeczywisty rozmiar pliku (rozmiar danych)
std::array<u_int, BLOCK_INDEX_NUMBER> directBlocks{}; //Bezpoœrednie indeksy
u_int singleIndirectBlocks; //Indeks bloku indeksowego, zpisywanego na dysku
//Dodatkowe informacje
tm creationTime = tm(); //Czas i data utworzenia
tm modificationTime = tm(); //Czas i data ostatniej modyfikacji pliku
//Synchronizacja
Semaphore sem;
bool opened = false;
Inode();
virtual ~Inode() = default;
void clear();
};
struct Disk {
//Tablica reprezentuj¹ca przestrzeñ dyskow¹ (jeden indeks - jeden bajt)
std::array<char, DISK_CAPACITY> space{};
//----------------------- Konstruktor -----------------------
Disk();
//-------------------------- Metody -------------------------
void write(const u_short_int& begin, const std::string& data);
void write(const u_short_int& begin, const std::array<u_int, BLOCK_SIZE / 2>& data);
const std::string read_str(const u_int& begin) const;
const std::array<u_int, BLOCK_SIZE / 2> read_arr(const u_int& begin) const;
} disk; //Struktura dysku
struct FileSystem {
u_int freeSpace{ DISK_CAPACITY }; //Zawiera informacje o iloœci wolnego miejsca na dysku (bajty)
//Wektor bitowy bloków (domyœlnie: 0 - wolny blok, 1 - zajêty blok)
std::bitset<DISK_CAPACITY / BLOCK_SIZE> bitVector;
/**
Tablica i-wêz³ów
*/
std::array<Inode, INODE_NUMBER_LIMIT> inodeTable;
//Pomocnicza tablica 'zajêtoœci' i-wêz³ów (1 - zajêty, 0 - wolny).
std::bitset<INODE_NUMBER_LIMIT> inodeBitVector;
std::unordered_map<std::string, u_int> rootDirectory;
FileSystem();
u_int get_free_inode_id();
void reset();
} fileSystem; //System plików
//Klasa odczytu/zapisu
class FileIO {
private:
#define READ_FLAG 0
#define WRITE_FLAG 1
std::string buffer;
u_short_int readPos = 0;
Disk* disk;
Inode* file;
bool readFlag;
bool writeFlag;
public:
FileIO() : disk(nullptr), file(nullptr), readFlag(false), writeFlag(false) {}
FileIO(Disk* disk, Inode* inode, const std::bitset<2>& mode) : disk(disk), file(inode),
readFlag(mode[READ_FLAG]), writeFlag(mode[WRITE_FLAG]) {}
void buffer_update(const int8_t& blockNumber);
std::string read(const u_short_int& byteNumber);
std::string read_all();
void reset_read_pos() { readPos = 0; }
void write(const std::vector<std::string>& dataFragments, const int8_t& startIndex) const;
const std::bitset<2> get_flags() const;
};
//------------------- Definicje zmiennych -------------------
bool messages = false; //Zmienna do w³¹czania/wy³¹czania powiadomieñ
bool detailedMessages = false; //Zmienna do w³¹czania/wy³¹czania szczegó³owych powiadomieñ
//Mapa dostêpu dla poszczególnych plików i procesów
//Klucz - para nazwa pliku, nazwa procesu
//WartoϾ - semafor przypisany danemu procesowi
std::map<std::pair<std::string, std::string>, FileIO> accessedFiles;
//Inne modu³y
public:
//----------------------- Konstruktor -----------------------
/**
Konstruktor domyœlny. Przypisuje do obecnego katalogu katalog g³ówny.
*/
explicit FileManager() = default;
//-------------------- Podstawowe Metody --------------------
/**
Tworzy plik o podanej nazwie w obecnym katalogu.\n
Po stworzeniu plik jest otwarty w trybie do zapisu.
@param fileName Nazwa pliku.
@param procName Nazwa procesu tworz¹cego.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_create(const std::string& fileName, const std::string& procName);
/**
Zapisuje podane dane w danym pliku usuwaj¹c poprzedni¹ zawartoœæ.
@param fileName Nazwa pliku.
@param procName Nazwa procesu, który chce zapisaæ do pliku.
@param data Dane do zapisu.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_write(const std::string& fileName, const std::string& procName, const std::string& data);
/**
Dopisuje podane dane na koniec pliku.
@param fileName Nazwa pliku.
@param procName Nazwa procesu, który chce dopisaæ do pliku.
@param data Dane do zapisu.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_append(const std::string& fileName, const std::string& procName, const std::string& data);
/**
Odczytuje podan¹ liczbê bajtów z pliku. Po odczycie przesuwa siê wskaŸnik odczytu.\n
Aby zresetowaæ wskaŸnik odczytu nale¿y ponownie otworzyæ plik.
@param fileName Nazwa pliku.
@param procName Nazwa procesu, który chce odczytaæ z pliku.
@param byteNumber Iloœæ bajtów do odczytu.
@param result Miejsce do zapisania odczytanych danych.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_read(const std::string& fileName, const std::string& procName, const u_short_int& byteNumber, std::string& result);
/**
Odczytuje ca³e dane z pliku.
@param fileName Nazwa pliku.
@param procName Nazwa procesu, który chce odczytaæ z pliku.
@param result Miejsca do zapisania odczytanych danych.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_read_all(const std::string& fileName, const std::string& procName, std::string& result);
/**
Usuwa plik o podanej nazwie znajduj¹cy siê w obecnym katalogu.\n
Plik jest wymazywany z katalogu g³ównego oraz wektora bitowego.
@param fileName Nazwa pliku.
@param procName Nazwa procesu, który chce usun¹æ pliku.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_delete(const std::string& fileName, const std::string& procName);
/**
Otwiera plik z podanym trybem dostêpu:
- R (read) - do odczytu
- W (write) - do zapisu
- RW (read/write) - do odczytu i zapisu
@param fileName Nazwa pliku.
@param procName Nazwa procesu tworz¹cego.
@param mode Tryb dostêpu do pliku.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_open(const std::string& fileName, const std::string& procName, const unsigned int& mode);
/**
Zamyka plik o podanej nazwie.
@param fileName Nazwa pliku.
@param procName Nazwa procesu, który zamkn¹æ pliku.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_close(const std::string& fileName, const std::string& procName);
//--------------------- Dodatkowe metody --------------------
/**
Sprawdza czy plik istnieje.
@param fileName Nazwa pliku do znalezienia.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
bool file_exists(const std::string& fileName);
/**
Zamyka wszystkie pliki dla danego procesu.
@param procName Nazwa procesu dla którego maj¹ byæ zamkniête pliki.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_close_all(const std::string& procName);
/**
Zamyka wszystkie pliki.
@return Kod b³êdu. 0 oznacza brak b³êdu.
*/
int file_close_all();
/**
Zmienia zmienn¹ odpowiadaj¹c¹ za wyœwietlanie komunikatów.
false - komunikaty wy³¹czone.
true - komunikaty w³¹czone.
@param onOff Czy komunikaty maj¹ byæ w³¹czone.
@return void.
*/
void set_messages(const bool& onOff);
/**
Zmienia zmienn¹ odpowiadaj¹c¹ za wyœwietlanie szczegó³owych komunikatów.
false - komunikaty wy³¹czone.
true - komunikaty w³¹czone.
@param onOff Czy komunikaty maj¹ byæ w³¹czone.
@return void.
*/
void set_detailed_messages(const bool& onOff);
//------------------ Metody do wyœwietlania -----------------
/**
Wyœwietla parametry systemu plików.
@return void.
*/
static void display_file_system_params();
/**
Wyœwietla informacje o wybranym katalogu.
@return void.
*/
void display_root_directory_info();
/**
Wyœwietla informacje o pliku.
@return True, jeœli operacja siê uda³a lub false, jeœli operacja nie powiod³a siê.
*/
int display_file_info(const std::string& name);
/**
Wyœwietla strukturê katalogów.
@return True, jeœli operacja siê uda³a lub false, jeœli operacja nie powiod³a siê.
*/
void display_root_directory();
/**
Wyœwietla zawartoœæ dysku jako znaki.
'.' - puste pole.
@return void.
*/
void display_disk_content_char();
/**
Wyœwietla wektor bitowy.
@return void.
*/
void display_bit_vector();
void display_block_char(const unsigned int& block);
//------ KOLEJNE METODY MA£O KOGO POWINNY OBCHODZIÆ ---------
private:
//------------------- Metody Sprawdzaj¹ce -------------------
bool check_if_name_used(const std::string& name);
bool check_if_enough_space(const u_int& dataSize) const;
//-------------------- Metody Obliczaj¹ce -------------------
static u_int calculate_needed_blocks(const size_t& dataSize);
size_t calculate_directory_size();
size_t calculate_directory_size_on_disk();
//--------------------- Metody Alokacji ---------------------
void file_truncate(Inode* file, const u_int& neededBlocks);
void file_add_indexes(Inode* file, const std::vector<u_int>& blocks);
void file_deallocate(Inode* file);
void file_allocate_blocks(Inode* file, const std::vector<u_int>& blocks);
void file_allocation_increase(Inode* file, const u_int& neededBlocks);
const std::vector<u_int> find_unallocated_blocks_fragmented(u_int blockNumber);
const std::vector<u_int> find_unallocated_blocks_best_fit(const u_int& blockNumber);
const std::vector<u_int> find_unallocated_blocks(const u_int& blockNumber);
//----------------------- Metody Inne -----------------------
bool is_file_opened_write(const std::string& fileName);
int file_accessing_proc_count(const std::string& fileName);
std::string get_file_data_block(Inode* file, const int8_t& indexNumber) const;
void file_write(Inode* file, FileIO* IO, const std::string& data);
void file_append(Inode* file, FileIO* IO, const std::string& data);
static const tm get_current_time_and_date();
void change_bit_vector_value(const u_int& block, const bool& value);
static const std::vector<std::string> fragmentate_data(const std::string& data);
};
extern FileManager fm;