From f7a2affb9f3cc6df39751f40c406e7bdf0e9097d Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Sat, 27 Aug 2016 13:48:10 -0400 Subject: [PATCH] file track system is ready for porting --- 4coder_default_include.cpp | 7 +- 4ed_api_implementation.cpp | 19 +- 4ed_file_view.cpp | 39 ++- build.bat | 2 +- build_all.bat | 8 +- filetrack/4tech_file_track_general.c | 270 +++++++++++++++ filetrack/4tech_file_track_win32.c | 498 +++++---------------------- internal_4coder_tests.cpp | 2 +- 8 files changed, 402 insertions(+), 443 deletions(-) create mode 100644 filetrack/4tech_file_track_general.c diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index 7f408843..420daefb 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -1930,9 +1930,10 @@ CUSTOM_COMMAND_SIG(open_all_code){ String extension = make_string(info->filename, info->filename_len, info->filename_len+1); extension = file_extension(extension); if (match(extension, make_lit_string("cpp")) || - match(extension, make_lit_string("hpp")) || - match(extension, make_lit_string("c")) || - match(extension, make_lit_string("h"))){ + match(extension, make_lit_string("hpp")) || + match(extension, make_lit_string("c")) || + match(extension, make_lit_string("h")) || + match(extension, make_lit_string("cc"))){ // NOTE(allen): There's no way in the 4coder API to use relative // paths at the moment, so everything should be full paths. Which is // managable. Here simply set the dir string size back to where it diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 5f2ca7a1..270eecd0 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -1094,7 +1094,7 @@ Kill_Buffer(Application_Links *app, Buffer_Identifier buffer, View_ID view_id, B DOC_PARAM(buffer, The buffer parameter specifies the buffer to try to kill.) DOC_PARAM(view_id, The view_id parameter specifies the view that will contain the "are you sure" dialogue if the buffer is dirty.) DOC_PARAM(flags, The flags parameter specifies behaviors for the buffer kill.) -DOC_RETURN(This call returns non-zero on success.) +DOC_RETURN(This call returns non-zero if the buffer is killed.) DOC ( Tries to kill the idenfied buffer. If the buffer is dirty and the "are you sure" @@ -1118,12 +1118,21 @@ DOC_SEE(Buffer_Identifier) kill_file(system, models, file); } else{ - if (vptr){ - result = true; - interactive_try_kill_file(system, models, vptr, file); + Try_Kill_Result kill_result = interactive_try_kill_file(system, models, file); + if (kill_result == TryKill_NeedDialogue){ + if (vptr){ + interactive_begin_sure_to_kill(system, vptr, file); + } + else{ +#define MESSAGE "CUSTOM WARNING: the buffer is dirty and no view was specified for a dialogue.\n" + app->print_message(app, literal(MESSAGE)); +#undef MESSAGE + } } else{ - app->print_message(app, literal("CUSTOM WARNING: the buffer is dirty and no view was specified for a dialogue.")); + if (kill_result == TryKill_Success){ + result = true; + } } } } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index c0ec0196..d8e68f85 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -3312,24 +3312,45 @@ save_file_by_name(System_Functions *system, Models *models, String name){ } } -internal b32 -interactive_try_kill_file(System_Functions *system, Models *models, View *view, Editing_File *file){ - b32 kill_dialogue = false; +internal void +interactive_begin_sure_to_kill(System_Functions *system, View *view, Editing_File *file){ + view_show_interactive(system, view, + IAct_Sure_To_Kill, IInt_Sure_To_Kill, + make_lit_string("Are you sure?")); + copy(&view->dest, file->name.live_name); +} + +enum Try_Kill_Result{ + TryKill_CannotKill, + TryKill_NeedDialogue, + TryKill_Success +}; + +internal Try_Kill_Result +interactive_try_kill_file(System_Functions *system, Models *models, Editing_File *file){ + Try_Kill_Result result = TryKill_CannotKill; if (!file->settings.never_kill){ if (buffer_needs_save(file)){ - view_show_interactive(system, view, - IAct_Sure_To_Kill, IInt_Sure_To_Kill, - make_lit_string("Are you sure?")); - copy(&view->dest, file->name.live_name); - kill_dialogue = true; + result = TryKill_NeedDialogue; } else{ kill_file(system, models, file); + result = TryKill_Success; } } - return(kill_dialogue); + return(result); +} + +internal b32 +interactive_try_kill_file(System_Functions *system, Models *models, View *view, Editing_File *file){ + Try_Kill_Result kill_result = interactive_try_kill_file(system, models, file); + b32 result = (kill_result == TryKill_NeedDialogue); + if (result){ + interactive_begin_sure_to_kill(system, view, file); + } + return(result); } internal b32 diff --git a/build.bat b/build.bat index c266190f..92aebd90 100644 --- a/build.bat +++ b/build.bat @@ -3,4 +3,4 @@ REM "build_exp.bat" /O2 "build_all.bat" /DFRED_SUPER /DFRED_INTERNAL /Zi REM "build_all.bat" /DFRED_INTERNAL /Zi -REM "build_all.bat" /O2 /Zi +REM "build_all.bat" /DFRED_SUPER /O2 /Zi diff --git a/build_all.bat b/build_all.bat index 538444d3..be47973f 100644 --- a/build_all.bat +++ b/build_all.bat @@ -26,16 +26,16 @@ popd pushd ..\build REM call "%CODE_DIR%\buildsuper.bat" ..\code\4coder_default_bindings.cpp -call "%CODE_DIR%\buildsuper.bat" ..\code\internal_4coder_tests.cpp +REM call "%CODE_DIR%\buildsuper.bat" ..\code\internal_4coder_tests.cpp REM call "%CODE_DIR%\buildsuper.bat" ..\code\power\4coder_casey.cpp REM call "%CODE_DIR%\buildsuper.bat" ..\4vim\4coder_chronal.cpp if %ERRORLEVEL% neq 0 (set FirstError=1) set EXPORTS=/EXPORT:app_get_functions -cl %OPTS% %INCLUDES% %DEFINES% %CODE_DIR%\4ed_app_target.cpp %* /Fe4ed_app /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS% +REM cl %OPTS% %INCLUDES% %DEFINES% %CODE_DIR%\4ed_app_target.cpp %* /Fe4ed_app /LD /link /DEBUG /INCREMENTAL:NO /OPT:REF %EXPORTS% if %ERRORLEVEL% neq 0 (set FirstError=1) -cl %OPTS% %INCLUDES% %DEFINES% %CODE_DIR%\win32_4ed.cpp %LIBS% %ICON% %* /Fe4ed /link /NODEFAULTLIB:library +cl %OPTS% %INCLUDES% %DEFINES% %CODE_DIR%\win32_4ed.cpp %LIBS% %ICON% %* /Fe4ed /link /DEBUG /NODEFAULTLIB:library if %ERRORLEVEL% neq 0 (set FirstError=1) call "print_size.bat" 4ed_app.dll @@ -46,5 +46,3 @@ popd call "ctime" -end 4ed_data.ctm %FirstError% - - diff --git a/filetrack/4tech_file_track_general.c b/filetrack/4tech_file_track_general.c new file mode 100644 index 00000000..4afff856 --- /dev/null +++ b/filetrack/4tech_file_track_general.c @@ -0,0 +1,270 @@ +/* + +Copy Right FourTech LLC, 2016 +All Rights Are Reserved + +The OS agnostic file tracking API for applications +that want to interact with potentially many files on +the disk that could be changed by other applications. + +Created on: 27.08.2016 + +*/ + + +// TOP + +#ifndef Assert +# define Assert(c) do { if (!(c)) { *((int*)0) = 0xA11E; } } while (0) +#endif + +#ifndef ZeroStruct +# define ZeroStruct(s) for (int32_t i = 0; i < sizeof(s); ++i) { ((char*)(&(s)))[i] = 0; } +#endif + +typedef struct{ + uint32_t id[4]; +} File_Index; + +typedef uint32_t rptr32; + +#define to_ptr(b,p) ((void*)((char*)b + p)) +#define to_rptr32(b,p) ((rptr32)((char*)(p) - (char*)(b))) + +typedef struct { + File_Index hash; + uint32_t opaque[4]; +} File_Track_Entry; + +typedef struct { + int32_t size; + uint32_t tracked_count; + uint32_t max; + rptr32 file_table; +} File_Track_Tables; + +typedef struct DLL_Node { + struct DLL_Node *next; + struct DLL_Node *prev; +} DLL_Node; + + + +static File_Index +zero_file_index(){ + File_Index a = {0}; + return(a); +} + +static int32_t +file_hash_is_zero(File_Index a){ + return ((a.id[0] == 0) && + (a.id[1] == 0) && + (a.id[2] == 0) && + (a.id[3] == 0)); +} + +static int32_t +file_hash_is_deleted(File_Index a){ + return ((a.id[0] == 0xFFFFFFFF) && + (a.id[1] == 0xFFFFFFFF) && + (a.id[2] == 0xFFFFFFFF) && + (a.id[3] == 0xFFFFFFFF)); +} + +static int32_t +file_index_eq(File_Index a, File_Index b){ + return ((a.id[0] == b.id[0]) && + (a.id[1] == b.id[1]) && + (a.id[2] == b.id[2]) && + (a.id[3] == b.id[3])); +} + +static void +insert_node(DLL_Node *pos, DLL_Node *node){ + node->prev = pos; + node->next = pos->next; + pos->next = node; + node->next->prev = node; +} + +static void +remove_node(DLL_Node *node){ + node->next->prev = node->prev; + node->prev->next = node->next; +} + +static void +init_sentinel_node(DLL_Node *node){ + node->next = node; + node->prev = node; +} + +static DLL_Node* +allocate_node(DLL_Node *sentinel){ + DLL_Node *result = 0; + if (sentinel->next != sentinel){ + result = sentinel->next; + remove_node(result); + } + return(result); +} + +#define FILE_ENTRY_COST (sizeof(File_Track_Entry)) + + +static int32_t +tracking_system_has_space(File_Track_Tables *tables, int32_t new_count){ + uint32_t count = tables->tracked_count; + uint32_t max = tables->max; + int32_t result = ((count + new_count)*8 < max*7); + return(result); +} + +static int32_t +entry_is_available(File_Track_Entry *entry){ + int32_t result = 0; + if (entry){ + result = + file_hash_is_zero(entry->hash) || + file_hash_is_deleted(entry->hash); + } + return (result); +} + +static File_Track_Entry* +tracking_system_lookup_entry(File_Track_Tables *tables, File_Index key){ + uint32_t hash = key.id[0]; + uint32_t max = tables->max; + uint32_t index = (hash) % max; + uint32_t start = index; + + File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table); + + File_Track_Entry* result = 0; + for (;;){ + File_Track_Entry *entry = entries + index; + + if (file_index_eq(entry->hash, key)){ + result = entry; + break; + } + else if (file_hash_is_zero(entry->hash)){ + if (result == 0){ + result = entry; + } + break; + } + else if (file_hash_is_deleted(entry->hash)){ + if (result == 0){ + result = entry; + } + } + + ++index; + if (index == max) index = 0; + if (index == start) break; + } + + return(result); +} + +static File_Track_Entry* +get_file_entry(File_Track_Tables *tables, File_Index index){ + File_Track_Entry *entry = 0; + + File_Track_Entry *result = tracking_system_lookup_entry(tables, index); + if (result && file_index_eq(index, result->hash)){ + entry = result; + } + + return(entry); +} + +static void +internal_free_slot(File_Track_Tables *tables, File_Track_Entry *entry){ + Assert(!entry_is_available(entry)); + + ZeroStruct(*entry); + entry->hash.id[0] = 0xFFFFFFFF; + entry->hash.id[1] = 0xFFFFFFFF; + entry->hash.id[2] = 0xFFFFFFFF; + entry->hash.id[3] = 0xFFFFFFFF; + + --tables->tracked_count; +} + +static int32_t +enough_memory_to_init_table(int32_t table_memory_size){ + int32_t result = (sizeof(File_Track_Tables) + FILE_ENTRY_COST*8 <= table_memory_size); + return(result); +} + +static void +init_table_memory(File_Track_Tables *tables, int32_t table_memory_size){ + tables->size = table_memory_size; + tables->tracked_count = 0; + + int32_t max_number_of_entries = + (table_memory_size - sizeof(*tables)) / FILE_ENTRY_COST; + + tables->file_table = sizeof(*tables); + tables->max = max_number_of_entries; +} + +static File_Track_Result +move_table_memory(File_Track_Tables *original_tables, + void *mem, int32_t size){ + File_Track_Result result = FileTrack_Good; + + if (original_tables->size < size){ + File_Track_Tables *tables = (File_Track_Tables*)mem; + + // NOTE(allen): Initialize main data tables + { + tables->size = size; + + int32_t likely_entry_size = FILE_ENTRY_COST; + int32_t max_number_of_entries = (size - sizeof(*tables)) / likely_entry_size; + + tables->file_table = sizeof(*tables); + tables->max = max_number_of_entries; + } + + if (tables->max > original_tables->max){ + uint32_t original_max = original_tables->max; + + // NOTE(allen): Rehash the tracking table + { + File_Track_Entry *entries = (File_Track_Entry*) + to_ptr(original_tables, original_tables->file_table); + + for (uint32_t index = 0; + index < original_max; + ++index){ + File_Track_Entry *entry = entries + index; + if (!entry_is_available(entry)){ + File_Index hash = entry->hash; + File_Track_Entry *lookup = + tracking_system_lookup_entry(tables, hash); + + Assert(entry_is_available(lookup)); + *lookup = *entry; + } + } + + tables->tracked_count = original_tables->tracked_count; + } + } + else{ + result = FileTrack_MemoryTooSmall; + } + } + else{ + result = FileTrack_MemoryTooSmall; + } + + return(result); +} + +// BOTTOM \ No newline at end of file diff --git a/filetrack/4tech_file_track_win32.c b/filetrack/4tech_file_track_win32.c index cf73ea69..be99a612 100644 --- a/filetrack/4tech_file_track_win32.c +++ b/filetrack/4tech_file_track_win32.c @@ -15,355 +15,61 @@ Created on: 20.07.2016 #include "4tech_file_track.h" +#include "4tech_file_track_general.c" + #include -#ifndef Assert -# define Assert(c) do { if (!(c)) { *((int*)0) = 0xA11E; } } while (0) -#endif - -#ifndef ZeroStruct -# define ZeroStruct(s) for (int32_t i = 0; i < sizeof(s); ++i) { ((char*)(&(s)))[i] = 0; } -#endif - -#ifndef NotImplemented -# define NotImplemented Assert(!"not implemented") -#endif - -typedef struct{ - uint32_t id[4]; -} File_Index; - -static File_Index -zero_file_index(){ - File_Index a = {0}; - return(a); -} - -static int32_t -file_index_eq(File_Index a, File_Index b){ - return ((a.id[0] == b.id[0]) && - (a.id[1] == b.id[1]) && - (a.id[2] == b.id[2]) && - (a.id[3] == b.id[3])); -} - -typedef uint32_t rptr32; - -typedef struct DLL_Node { - struct DLL_Node *next; - struct DLL_Node *prev; -} DLL_Node; - typedef struct { + char result[2048]; OVERLAPPED overlapped; HANDLE dir; int32_t user_count; - - char result[2048]; -} Directory_Listener; +} Win32_Directory_Listener; typedef struct { DLL_Node node; - Directory_Listener listener; -} Directory_Listener_Node; + Win32_Directory_Listener listener; +} Win32_Directory_Listener_Node; typedef struct { HANDLE iocp; CRITICAL_SECTION table_lock; - void *tables; DLL_Node free_sentinel; - -} File_Track_Vars; +} Win32_File_Track_Vars; typedef struct { - int32_t size; - uint32_t tracked_count; - uint32_t max; - rptr32 file_table; -} File_Track_Tables; - -typedef struct { - HANDLE dir; File_Index hash; - Directory_Listener_Node *listener_node; -} File_Track_Entry; + HANDLE dir; + Win32_Directory_Listener_Node *listener_node; +} Win32_File_Track_Entry; -#define FILE_ENTRY_COST (sizeof(File_Track_Entry)) - -#define to_vars_(s) ((File_Track_Vars*)(s)) +#define to_vars(s) ((Win32_File_Track_Vars*)(s)) #define to_tables(v) ((File_Track_Tables*)(v->tables)) -#define to_ptr(b,p) ((void*)((char*)b + p)) -#define to_rptr32(b,p) ((rptr32)((char*)(p) - (char*)(b))) - -static void -insert_node(DLL_Node *pos, DLL_Node *node){ - node->prev = pos; - node->next = pos->next; - pos->next = node; - node->next->prev = node; -} - -static void -remove_node(DLL_Node *node){ - node->next->prev = node->prev; - node->prev->next = node->next; -} - -static void -init_sentinel_node(DLL_Node *node){ - node->next = node; - node->prev = node; -} - -static DLL_Node* -allocate_node(DLL_Node *sentinel){ - DLL_Node *result = 0; - if (sentinel->next != sentinel){ - result = sentinel->next; - remove_node(result); - } - return(result); -} - -static int32_t -file_hash_is_zero(File_Index a){ - return ((a.id[0] == 0) && - (a.id[1] == 0) && - (a.id[2] == 0) && - (a.id[3] == 0)); -} - -static int32_t -file_hash_is_deleted(File_Index a){ - return ((a.id[0] == 0xFFFFFFFF) && - (a.id[1] == 0xFFFFFFFF) && - (a.id[2] == 0xFFFFFFFF) && - (a.id[3] == 0xFFFFFFFF)); -} - -static int32_t -tracking_system_has_space(File_Track_Tables *tables, int32_t new_count){ - uint32_t count = tables->tracked_count; - uint32_t max = tables->max; - int32_t result = ((count + new_count)*8 < max*7); - return(result); -} - -static int32_t -entry_is_available(File_Track_Entry *entry){ - int32_t result = 0; - if (entry){ - result = - file_hash_is_zero(entry->hash) || - file_hash_is_deleted(entry->hash); - } - return (result); -} - -typedef struct{ - File_Track_Entry *entry; -} File_Lookup_Result; - -static File_Lookup_Result -tracking_system_lookup_entry(File_Track_Tables *tables, File_Index key){ - uint32_t hash = key.id[0]; - uint32_t max = tables->max; - uint32_t index = (hash) % max; - uint32_t start = index; - - File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table); - - File_Lookup_Result result = {0}; - - for (;;){ - File_Track_Entry *entry = entries + index; - - if (file_index_eq(entry->hash, key)){ - result.entry = entry; - break; - } - else if (file_hash_is_zero(entry->hash)){ - if (result.entry == 0){ - result.entry = entry; - } - break; - } - else if (file_hash_is_deleted(entry->hash)){ - if (result.entry == 0){ - result.entry = entry; - } - } - - ++index; - if (index == max) index = 0; - if (index == start) break; - } - - return(result); -} - -static File_Track_Entry* -get_file_entry(File_Track_Tables *tables, File_Index index){ - File_Track_Entry *entry = 0; - - File_Lookup_Result result = tracking_system_lookup_entry(tables, index); - if (result.entry && file_index_eq(index, result.entry->hash)){ - entry = result.entry; - } - - return(entry); -} - -#if 0 -static DWORD -directory_watching(LPVOID ptr){ - File_Track_Vars *vars = to_vars_(ptr); - OVERLAPPED *overlapped = 0; - DWORD length = 0; - ULONG_PTR key = 0; - - for (;;){ - GetQueuedCompletionStatus( - vars->iocp, - &length, - &key, - &overlapped, - INFINITE - ); - - Directory_Listener *listener_ptr = (Directory_Listener*)overlapped; - Directory_Listener listener = *listener_ptr; - - ZeroStruct(listener_ptr->overlapped); - ReadDirectoryChangesW(listener_ptr->dir, - listener_ptr->result, - sizeof(listener_ptr->result), - 0, - FILE_NOTIFY_CHANGE_LAST_WRITE, - 0, - &listener_ptr->overlapped, - 0); - - { - EnterCriticalSection(&vars->table_lock); - - File_Track_Tables *tables = to_tables(vars); - File_Change_Record *records = (File_Change_Record*) - to_ptr(tables, tables->change_queue); - - char *buffer = listener.result; - DWORD offset = 0; - FILE_NOTIFY_INFORMATION *info = 0; - - for (;;){ - info = (FILE_NOTIFY_INFORMATION*)(buffer + offset); - - // TODO(allen): make this real - int32_t success = 0; - char filename[512]; - int32_t len = info->FileNameLength / 2; - int32_t pos = 0; - - char *src = listener.dir_name; - for (int32_t i = 0; src[i]; ++i, ++pos){ - filename[pos] = src[i]; - } - - if (len + pos + 1 < sizeof(filename)){ - filename[pos++] = '/'; - - for (int32_t i = 0; i < len; ++i, ++pos){ - filename[pos] = (char)info->FileName[i]; - } - filename[pos] = 0; - - success = 1; - } - - if (success){ - File_Index change_index = zero_file_index(); - File_Track_Entry *entry = 0; - File_Track_Result result = - internal_get_tracked_file_index(tables, filename, &change_index, &entry); - - if (result == FileTrack_Good){ - BY_HANDLE_FILE_INFORMATION info = {0}; - - if (GetFileInformationByHandle(entry->file, &info)){ - if (entry->skip_change){ - entry->skip_change = 0; - } - else{ - File_Change_Record *record = 0; - - if (entry->change_pos == -1){ - int32_t write_pos = tables->change_write_pos; - if (tables->change_write_pos + 1 == tables->change_read_pos){ - break; - } - - tables->change_write_pos += 1; - entry->change_pos = write_pos; - - record = records + write_pos; - } - else{ - record = records + entry->change_pos; - } - - record->index = entry->hash; - record->still_active = 1; - } - } - } - } - - if (info->NextEntryOffset != 0){ - offset += info->NextEntryOffset; - } - else{ - break; - } - } - - LeaveCriticalSection(&vars->table_lock); - } - } -} -#endif File_Track_Result init_track_system(File_Track_System *system, void *table_memory, int32_t table_memory_size, void *listener_memory, int32_t listener_memory_size){ File_Track_Result result = FileTrack_MemoryTooSmall; - File_Track_Vars *vars = to_vars_(system); + Win32_File_Track_Vars *vars = to_vars(system); - if (sizeof(File_Track_Tables) + FILE_ENTRY_COST*8 <= table_memory_size && - sizeof(Directory_Listener_Node) <= listener_memory_size){ - vars->tables = table_memory; - - File_Track_Tables *tables = to_tables(vars); + Assert(sizeof(Win32_File_Track_Entry) <= sizeof(File_Track_Entry)); + + if (enough_memory_to_init_table(table_memory_size) && + sizeof(Win32_Directory_Listener_Node) <= listener_memory_size){ // NOTE(allen): Initialize main data tables - { - tables->size = table_memory_size; - tables->tracked_count = 0; - - int32_t likely_entry_size = FILE_ENTRY_COST; - int32_t max_number_of_entries = (table_memory_size - sizeof(*tables)) / likely_entry_size; - - tables->file_table = sizeof(*tables); - tables->max = max_number_of_entries; - } + vars->tables = table_memory; + File_Track_Tables *tables = to_tables(vars); + init_table_memory(tables, table_memory_size); // NOTE(allen): Initialize nodes of directory watching { init_sentinel_node(&vars->free_sentinel); - Directory_Listener_Node *listener = (Directory_Listener_Node*)listener_memory; - int32_t count = listener_memory_size / sizeof(Directory_Listener_Node); + Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)listener_memory; + int32_t count = listener_memory_size / sizeof(Win32_Directory_Listener_Node); for (int32_t i = 0; i < count; ++i, ++listener){ insert_node(&vars->free_sentinel, &listener->node); } @@ -414,23 +120,10 @@ internal_get_file_index(BY_HANDLE_FILE_INFORMATION info){ return(hash); } -static void -internal_free_slot(File_Track_Tables *tables, File_Track_Entry *entry){ - Assert(!entry_is_available(entry)); - - ZeroStruct(*entry); - entry->hash.id[0] = 0xFFFFFFFF; - entry->hash.id[1] = 0xFFFFFFFF; - entry->hash.id[2] = 0xFFFFFFFF; - entry->hash.id[3] = 0xFFFFFFFF; - - --tables->tracked_count; -} - File_Track_Result add_listener(File_Track_System *system, char *filename){ File_Track_Result result = FileTrack_Good; - File_Track_Vars *vars = to_vars_(system); + Win32_File_Track_Vars *vars = to_vars(system); EnterCriticalSection(&vars->table_lock); { @@ -455,11 +148,12 @@ add_listener(File_Track_System *system, char *filename){ if (getinfo_result){ File_Index dir_hash = internal_get_file_index(dir_info); - File_Lookup_Result dir_lookup = tracking_system_lookup_entry(tables, dir_hash); + File_Track_Entry *dir_lookup = tracking_system_lookup_entry(tables, dir_hash); + Win32_File_Track_Entry *win32_entry = (Win32_File_Track_Entry*)dir_lookup; - if (entry_is_available(dir_lookup.entry)){ + if (entry_is_available(dir_lookup)){ if (tracking_system_has_space(tables, 1)){ - Directory_Listener_Node *node = (Directory_Listener_Node*) + Win32_Directory_Listener_Node *node = (Win32_Directory_Listener_Node*) allocate_node(&vars->free_sentinel); if (node){ if (CreateIoCompletionPort(dir, vars->iocp, (ULONG_PTR)node, 1)){ @@ -475,9 +169,9 @@ add_listener(File_Track_System *system, char *filename){ node->listener.dir = dir; node->listener.user_count = 1; - dir_lookup.entry->hash = dir_hash; - dir_lookup.entry->dir = dir; - dir_lookup.entry->listener_node = node; + win32_entry->hash = dir_hash; + win32_entry->dir = dir; + win32_entry->listener_node = node; ++tables->tracked_count; } else{ @@ -501,7 +195,7 @@ add_listener(File_Track_System *system, char *filename){ } } else{ - Directory_Listener_Node *node = dir_lookup.entry->listener_node; + Win32_Directory_Listener_Node *node = win32_entry->listener_node; ++node->listener.user_count; } } @@ -525,7 +219,7 @@ add_listener(File_Track_System *system, char *filename){ File_Track_Result remove_listener(File_Track_System *system, char *filename){ File_Track_Result result = FileTrack_Good; - File_Track_Vars *vars = to_vars_(system); + Win32_File_Track_Vars *vars = to_vars(system); EnterCriticalSection(&vars->table_lock); @@ -551,16 +245,17 @@ remove_listener(File_Track_System *system, char *filename){ if (getinfo_result){ File_Index dir_hash = internal_get_file_index(dir_info); - File_Lookup_Result dir_lookup = tracking_system_lookup_entry(tables, dir_hash); + File_Track_Entry *dir_lookup = tracking_system_lookup_entry(tables, dir_hash); + Win32_File_Track_Entry *win32_dir = (Win32_File_Track_Entry*)dir_lookup; - Assert(!entry_is_available(dir_lookup.entry)); - Directory_Listener_Node *node = dir_lookup.entry->listener_node; + Assert(!entry_is_available(dir_lookup)); + Win32_Directory_Listener_Node *node = win32_dir->listener_node; --node->listener.user_count; if (node->listener.user_count == 0){ insert_node(&vars->free_sentinel, &node->node); - CloseHandle(dir_lookup.entry->dir); - internal_free_slot(tables, dir_lookup.entry); + CloseHandle(win32_dir->dir); + internal_free_slot(tables, dir_lookup); } } else{ @@ -582,62 +277,16 @@ remove_listener(File_Track_System *system, char *filename){ File_Track_Result move_track_system(File_Track_System *system, void *mem, int32_t size){ File_Track_Result result = FileTrack_Good; - File_Track_Vars *vars = to_vars_(system); + Win32_File_Track_Vars *vars = to_vars(system); EnterCriticalSection(&vars->table_lock); - - File_Track_Tables *original_tables = to_tables(vars); - - if (original_tables->size < size){ - File_Track_Tables *tables = (File_Track_Tables*)mem; - - // NOTE(allen): Initialize main data tables - { - tables->size = size; - - int32_t likely_entry_size = FILE_ENTRY_COST; - int32_t max_number_of_entries = (size - sizeof(*tables)) / likely_entry_size; - - tables->file_table = sizeof(*tables); - tables->max = max_number_of_entries; - } - - if (tables->max > original_tables->max){ - uint32_t original_max = original_tables->max; - - // NOTE(allen): Rehash the tracking table - { - File_Track_Entry *entries = (File_Track_Entry*) - to_ptr(original_tables, original_tables->file_table); - - for (uint32_t index = 0; - index < original_max; - ++index){ - File_Track_Entry *entry = entries + index; - if (!entry_is_available(entry)){ - File_Index hash = entry->hash; - File_Lookup_Result lookup = - tracking_system_lookup_entry(tables, hash); - Assert(entry_is_available(lookup.entry)); - - *lookup.entry = *entry; - } - } - - tables->tracked_count = original_tables->tracked_count; - } - - // NOTE(allen): Update to the new table + { + File_Track_Tables *original_tables = to_tables(vars); + result = move_table_memory(original_tables, mem, size); + if (result == FileTrack_Good){ vars->tables = mem; } - else{ - result = FileTrack_MemoryTooSmall; - } } - else{ - result = FileTrack_MemoryTooSmall; - } - LeaveCriticalSection(&vars->table_lock); return(result); @@ -646,13 +295,13 @@ move_track_system(File_Track_System *system, void *mem, int32_t size){ File_Track_Result expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size){ File_Track_Result result = FileTrack_Good; - File_Track_Vars *vars = to_vars_(system); + Win32_File_Track_Vars *vars = to_vars(system); EnterCriticalSection(&vars->table_lock); - if (sizeof(Directory_Listener_Node) <= size){ - Directory_Listener_Node *listener = (Directory_Listener_Node*)mem; - int32_t count = size / sizeof(Directory_Listener_Node); + if (sizeof(Win32_Directory_Listener_Node) <= size){ + Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)mem; + int32_t count = size / sizeof(Win32_Directory_Listener_Node); for (int32_t i = 0; i < count; ++i, ++listener){ insert_node(&vars->free_sentinel, &listener->node); } @@ -669,7 +318,7 @@ expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size File_Track_Result get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t *size){ File_Track_Result result = FileTrack_NoMoreEvents; - File_Track_Vars *vars = to_vars_(system); + Win32_File_Track_Vars *vars = to_vars(system); EnterCriticalSection(&vars->table_lock); @@ -684,8 +333,11 @@ get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t * &overlapped, 0)){ - Directory_Listener *listener_ptr = (Directory_Listener*)overlapped; - Directory_Listener listener = *listener_ptr; + Win32_Directory_Listener *listener_ptr = (Win32_Directory_Listener*)overlapped; + + // NOTE(allen): Get a copy of the state of this node so we can set the node + // to work listening for changes again right away. + Win32_Directory_Listener listener = *listener_ptr; ZeroStruct(listener_ptr->overlapped); ReadDirectoryChangesW(listener_ptr->dir, @@ -705,14 +357,16 @@ get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t * info = (FILE_NOTIFY_INFORMATION*)(listener_buffer + offset); int32_t len = info->FileNameLength / 2; - int32_t dir_len =GetFinalPathNameByHandle(listener.dir, 0, 0, FILE_NAME_NORMALIZED); + int32_t dir_len = GetFinalPathNameByHandle(listener.dir, 0, 0, + FILE_NAME_NORMALIZED); int32_t req_size = dir_len + 1 + len; *size = req_size; if (req_size < max){ int32_t pos = 0; - pos = GetFinalPathNameByHandle(listener.dir, buffer, max, FILE_NAME_NORMALIZED); - buffer[pos++] = '/'; + pos = GetFinalPathNameByHandle(listener.dir, buffer, max, + FILE_NAME_NORMALIZED); + buffer[pos++] = '\\'; for (int32_t i = 0; i < len; ++i, ++pos){ buffer[pos] = (char)info->FileName[i]; @@ -757,32 +411,38 @@ get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t * File_Track_Result shut_down_track_system(File_Track_System *system){ File_Track_Result result = FileTrack_Good; - File_Track_Vars *vars = to_vars_(system); + Win32_File_Track_Vars *vars = to_vars(system); - File_Track_Tables *tables = to_tables(vars); - - File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table); - - uint32_t index = 0; - uint32_t max = tables->max; DWORD win32_result = 0; - for (; index < max; ++index){ - File_Track_Entry *entry = entries + index; - if (!entry_is_available(entry)){ - if (!CloseHandle(entry->dir)){ - win32_result = 1; + // NOTE(allen): Close all the handles stored in the table. + { + File_Track_Tables *tables = to_tables(vars); + + File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table); + uint32_t max = tables->max; + + for (uint32_t index = 0; index < max; ++index){ + File_Track_Entry *entry = entries + index; + + if (!entry_is_available(entry)){ + Win32_File_Track_Entry *win32_entry = (Win32_File_Track_Entry*)entry; + if (!CloseHandle(win32_entry->dir)){ + win32_result = 1; + } } } } - if (!CloseHandle(vars->iocp)){ - win32_result = 1; + // NOTE(allen): Close all the global track system resources. + { + if (!CloseHandle(vars->iocp)){ + win32_result = 1; + } + DeleteCriticalSection(&vars->table_lock); } - DeleteCriticalSection(&vars->table_lock); - if (win32_result){ result = FileTrack_FileSystemError; } diff --git a/internal_4coder_tests.cpp b/internal_4coder_tests.cpp index 82706f7d..9c956014 100644 --- a/internal_4coder_tests.cpp +++ b/internal_4coder_tests.cpp @@ -55,7 +55,7 @@ CUSTOM_COMMAND_SIG(load_lots_of_files){ app->free_file_list(app, list); // TODO(allen): Pass this time test! - TEST_TIME_E(); + //TEST_TIME_E(); } CUSTOM_COMMAND_SIG(reopen_test){