cinera: Lock database and config files
This commit aims to help Cinera instances coordinate themselves by throwing an error upon being instructed to use a database or config file currently in use by another instance.
This commit is contained in:
		
							parent
							
								
									1cf703e346
								
							
						
					
					
						commit
						f60cf3087f
					
				
							
								
								
									
										666
									
								
								cinera/cinera.c
								
								
								
								
							
							
						
						
									
										666
									
								
								cinera/cinera.c
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -8,12 +8,6 @@ exit | |||
| 
 | ||||
| // config
 | ||||
| //
 | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <stdarg.h> | ||||
| 
 | ||||
| #define ArgCountPointer(...) (sizeof((void *[]){__VA_ARGS__})/sizeof(void *)) | ||||
| 
 | ||||
| #define DigitsInInt(I) DigitsInInt_(I, sizeof(*I)) | ||||
|  | @ -348,6 +342,15 @@ PushTokens(memory_book *TokensList) | |||
|     return This; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| PopTokens(memory_book *TokensList) | ||||
| { | ||||
|     --TokensList->ItemCount; | ||||
|     tokens *This = GetPlaceInBook(TokensList, TokensList->ItemCount); | ||||
|     FreeBook(&This->Token); | ||||
|     This->CurrentLine = 0; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| FreeTokensList(memory_book *TokensList) | ||||
| { | ||||
|  | @ -357,7 +360,8 @@ FreeTokensList(memory_book *TokensList) | |||
|         This->CurrentIndex = 0; | ||||
|         This->CurrentLine = 0; | ||||
|         FreeBook(&This->Token); | ||||
|         FreeFile(&This->File); | ||||
|         FreeFileBufferAndPath(&This->File); // NOTE(matt):  Not closing file because the next time we touch this handle is in
 | ||||
|                                             //              RemoveAndFreeWatchHandles() where we will close it
 | ||||
|     } | ||||
|     TokensList->ItemCount = 0; | ||||
| } | ||||
|  | @ -588,194 +592,204 @@ typedef struct | |||
| } config; | ||||
| 
 | ||||
| char *ExpandPath(string Path, string *RelativeToFile); // NOTE(matt): Forward declared. Consider reorganising the code?
 | ||||
| void PushWatchHandle(string Path, extension_id Extension, watch_type Type, project *Project, asset *Asset); // NOTE(matt): Forward declared. Consider reorganising the code?
 | ||||
| watch_file *PushWatchHandle(string Path, extension_id Extension, watch_type Type, project *Project, asset *Asset); // NOTE(matt): Forward declared. Consider reorganising the code?
 | ||||
| 
 | ||||
| tokens * | ||||
| Tokenise(memory_book *TokensList, string Path) | ||||
| Tokenise(memory_book *TokensList, string Path, string *Filename, uint64_t LineNumber) | ||||
| { | ||||
|     tokens *Result = 0; | ||||
|     char *Path0 = MakeString0("l", &Path); | ||||
|     FILE *Handle = 0; | ||||
|     PushWatchHandle(Path, EXT_NULL, WT_CONFIG, 0, 0); | ||||
|     if((Handle = fopen(Path0, "r"))) | ||||
|     watch_file *WatchFile = PushWatchHandle(Path, EXT_NULL, WT_CONFIG, 0, 0); | ||||
| 
 | ||||
|     Result = PushTokens(TokensList); | ||||
|     Result->File = InitFile(0, &Path, EXT_NULL, TRUE); | ||||
|     switch(ReadFileIntoBuffer(&Result->File)) | ||||
|     { | ||||
|         fclose(Handle); | ||||
| 
 | ||||
|         Result = PushTokens(TokensList); | ||||
|         Result->File = InitFile(0, &Path, EXT_NULL); | ||||
|         ReadFileIntoBuffer(&Result->File); | ||||
|         buffer *B = &Result->File.Buffer; | ||||
|         SkipWhitespace(Result, B); | ||||
|         while(B->Ptr - B->Location < B->Size) | ||||
|         { | ||||
|             token T = {}; | ||||
|             uint64_t Advancement = 0; | ||||
| 
 | ||||
|             if(!StringsDifferS(TokenStrings[TOKEN_COMMENT_SINGLE], B)) | ||||
|         case RC_ERROR_FILE_LOCKED: | ||||
|             { | ||||
|                 T.Type = TOKEN_COMMENT; | ||||
|                 B->Ptr += StringLength(TokenStrings[TOKEN_COMMENT_SINGLE]); | ||||
|                 SkipWhitespace(Result, B); | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 while(B->Ptr && *B->Ptr != '\n') | ||||
|                 { | ||||
|                     ++T.Content.Length; | ||||
|                     ++B->Ptr; | ||||
|                 } | ||||
|                 if(*B->Ptr == '\n') | ||||
|                 { | ||||
|                     ++Result->CurrentLine; | ||||
|                 } | ||||
|                 Advancement = 1; | ||||
|             } | ||||
|             else if(!StringsDifferS(TokenStrings[TOKEN_COMMENT_MULTI_OPEN], B)) | ||||
|                 ConfigErrorLockedConfigLocation(Filename, LineNumber, &Path); | ||||
|                 FreeFile(&Result->File, TRUE); | ||||
|                 PopTokens(TokensList); | ||||
|                 Result = 0; | ||||
|             } break; | ||||
|         case RC_ERROR_FILE: | ||||
|             { | ||||
|                 uint64_t CommentDepth = 1; | ||||
|                 T.Type = TOKEN_COMMENT; | ||||
|                 B->Ptr += StringLength(TokenStrings[TOKEN_COMMENT_MULTI_OPEN]); | ||||
|                 ConfigErrorUnopenableConfigLocation(Filename, LineNumber, &Path); | ||||
|                 FreeFile(&Result->File, TRUE); | ||||
|                 PopTokens(TokensList); | ||||
|                 Result = 0; | ||||
|             } break; | ||||
|         default: | ||||
|             { | ||||
|                 WatchFile->Handle = Result->File.Handle; | ||||
| 
 | ||||
|                 buffer *B = &Result->File.Buffer; | ||||
|                 SkipWhitespace(Result, B); | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 while(B->Ptr - B->Location < B->Size && CommentDepth) | ||||
|                 while(B->Ptr - B->Location < B->Size) | ||||
|                 { | ||||
|                     if(!StringsDifferS(TokenStrings[TOKEN_COMMENT_MULTI_CLOSE], B)) | ||||
|                     token T = {}; | ||||
|                     uint64_t Advancement = 0; | ||||
| 
 | ||||
|                     if(!StringsDifferS(TokenStrings[TOKEN_COMMENT_SINGLE], B)) | ||||
|                     { | ||||
|                         --CommentDepth; | ||||
|                         B->Ptr += StringLength(TokenStrings[TOKEN_COMMENT_MULTI_CLOSE]); | ||||
|                     } | ||||
|                     else if(B->Ptr - B->Location < B->Size && *B->Ptr == '\n') | ||||
|                     { | ||||
|                         ++Result->CurrentLine; | ||||
|                         ++B->Ptr; | ||||
|                         T.Type = TOKEN_COMMENT; | ||||
|                         B->Ptr += StringLength(TokenStrings[TOKEN_COMMENT_SINGLE]); | ||||
|                         SkipWhitespace(Result, B); | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         while(B->Ptr && *B->Ptr != '\n') | ||||
|                         { | ||||
|                             ++T.Content.Length; | ||||
|                             ++B->Ptr; | ||||
|                         } | ||||
|                         if(*B->Ptr == '\n') | ||||
|                         { | ||||
|                             ++Result->CurrentLine; | ||||
|                         } | ||||
|                         Advancement = 1; | ||||
|                     } | ||||
|                     else if(!StringsDifferS(TokenStrings[TOKEN_COMMENT_MULTI_OPEN], B)) | ||||
|                     { | ||||
|                         ++CommentDepth; | ||||
|                         uint64_t CommentDepth = 1; | ||||
|                         T.Type = TOKEN_COMMENT; | ||||
|                         B->Ptr += StringLength(TokenStrings[TOKEN_COMMENT_MULTI_OPEN]); | ||||
|                         SkipWhitespace(Result, B); | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         while(B->Ptr - B->Location < B->Size && CommentDepth) | ||||
|                         { | ||||
|                             if(!StringsDifferS(TokenStrings[TOKEN_COMMENT_MULTI_CLOSE], B)) | ||||
|                             { | ||||
|                                 --CommentDepth; | ||||
|                                 B->Ptr += StringLength(TokenStrings[TOKEN_COMMENT_MULTI_CLOSE]); | ||||
|                             } | ||||
|                             else if(B->Ptr - B->Location < B->Size && *B->Ptr == '\n') | ||||
|                             { | ||||
|                                 ++Result->CurrentLine; | ||||
|                                 ++B->Ptr; | ||||
|                             } | ||||
|                             else if(!StringsDifferS(TokenStrings[TOKEN_COMMENT_MULTI_OPEN], B)) | ||||
|                             { | ||||
|                                 ++CommentDepth; | ||||
|                                 B->Ptr += StringLength(TokenStrings[TOKEN_COMMENT_MULTI_OPEN]); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 ++B->Ptr; | ||||
|                             } | ||||
|                         } | ||||
|                         T.Content.Length = B->Ptr - T.Content.Base; | ||||
|                         Advancement = 0;//StringLength(TokenStrings[TOKEN_COMMENT_MULTI_CLOSE]);
 | ||||
|                     } | ||||
|                     else if(!StringsDifferS(TokenStrings[TOKEN_COMMENT_MULTI_CLOSE], B)) | ||||
|                     { | ||||
|                         Advancement = 2; | ||||
|                         T.Type = TOKEN_NULL; | ||||
|                         string Char = { .Base = B->Ptr, .Length = 2 }; | ||||
|                         string Filepath = Wrap0(Result->File.Path); | ||||
|                         ConfigError(&Filepath, Result->CurrentLine, S_WARNING, "Mismatched closing multiline comment marker: ", &Char); | ||||
|                     } | ||||
|                     else if(!StringsDifferS(TokenStrings[TOKEN_DOUBLEQUOTE], B)) | ||||
|                     { | ||||
|                         T.Type = TOKEN_STRING; | ||||
|                         ++B->Ptr; | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         while(B->Ptr - B->Location < B->Size && *B->Ptr != '"') | ||||
|                         { | ||||
|                             if(*B->Ptr == '\\') | ||||
|                             { | ||||
|                                 ++T.Content.Length; | ||||
|                                 ++B->Ptr; | ||||
|                             } | ||||
|                             ++T.Content.Length; | ||||
|                             ++B->Ptr; | ||||
|                         } | ||||
|                         Advancement = 1; | ||||
|                     } | ||||
|                     else if(!StringsDifferS(TokenStrings[TOKEN_MINUS], B)) | ||||
|                     { | ||||
|                         T.Type = TOKEN_MINUS; | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         ++T.Content.Length; | ||||
|                         Advancement = 1; | ||||
|                     } | ||||
|                     else if(!StringsDifferS(TokenStrings[TOKEN_ASSIGN], B)) | ||||
|                     { | ||||
|                         T.Type = TOKEN_ASSIGN; | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         ++T.Content.Length; | ||||
|                         Advancement = 1; | ||||
|                     } | ||||
|                     else if(!StringsDifferS(TokenStrings[TOKEN_OPEN_BRACE], B)) | ||||
|                     { | ||||
|                         T.Type = TOKEN_OPEN_BRACE; | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         ++T.Content.Length; | ||||
|                         Advancement = 1; | ||||
|                     } | ||||
|                     else if(!StringsDifferS(TokenStrings[TOKEN_CLOSE_BRACE], B)) | ||||
|                     { | ||||
|                         T.Type = TOKEN_CLOSE_BRACE; | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         ++T.Content.Length; | ||||
|                         Advancement = 1; | ||||
|                     } | ||||
|                     else if(!StringsDifferS(TokenStrings[TOKEN_SEMICOLON], B)) | ||||
|                     { | ||||
|                         T.Type = TOKEN_SEMICOLON; | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         ++T.Content.Length; | ||||
|                         Advancement = 1; | ||||
|                     } | ||||
|                     else if(IsValidIdentifierCharacter(*B->Ptr)) | ||||
|                     { | ||||
|                         T.Type = TOKEN_IDENTIFIER; | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         while(IsValidIdentifierCharacter(*B->Ptr)) | ||||
|                         { | ||||
|                             ++T.Content.Length; | ||||
|                             ++B->Ptr; | ||||
|                         } | ||||
|                         Advancement = 0; | ||||
|                     } | ||||
|                     else if(IsNumber(*B->Ptr)) | ||||
|                     { | ||||
|                         T.Type = TOKEN_NUMBER; | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         while(IsNumber(*B->Ptr)) | ||||
|                         { | ||||
|                             ++T.Content.Length; | ||||
|                             ++B->Ptr; | ||||
|                         } | ||||
|                         Advancement = 0; | ||||
|                     } | ||||
|                     else if(*B->Ptr == '\n') | ||||
|                     { | ||||
|                         T.Type = TOKEN_NEWLINE; | ||||
|                         T.Content.Base = B->Ptr; | ||||
|                         T.Content.Length = 1; | ||||
|                         ++Result->CurrentLine; | ||||
|                         Advancement = 1; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         ++B->Ptr; | ||||
|                         T.Type = TOKEN_NULL; | ||||
|                         string Char = GetUTF8Character(B->Ptr, B->Size - (B->Ptr - B->Location)); | ||||
|                         Advancement = Char.Length; | ||||
|                         string Filepath = Wrap0(Result->File.Path); | ||||
|                         if(Char.Base) | ||||
|                         { | ||||
|                             ConfigError(&Filepath, Result->CurrentLine, S_WARNING, "Unhandled character (ignored): ", &Char); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             ConfigErrorInt(&Filepath, Result->CurrentLine, S_WARNING, "Malformed UTF-8 bytes encountered (skipped): ", Char.Length); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 T.Content.Length = B->Ptr - T.Content.Base; | ||||
|                 Advancement = 0;//StringLength(TokenStrings[TOKEN_COMMENT_MULTI_CLOSE]);
 | ||||
|             } | ||||
|             else if(!StringsDifferS(TokenStrings[TOKEN_COMMENT_MULTI_CLOSE], B)) | ||||
|             { | ||||
|                 Advancement = 2; | ||||
|                 T.Type = TOKEN_NULL; | ||||
|                 string Char = { .Base = B->Ptr, .Length = 2 }; | ||||
|                 string Filepath = Wrap0(Result->File.Path); | ||||
|                 ConfigError(&Filepath, Result->CurrentLine, S_WARNING, "Mismatched closing multiline comment marker: ", &Char); | ||||
|             } | ||||
|             else if(!StringsDifferS(TokenStrings[TOKEN_DOUBLEQUOTE], B)) | ||||
|             { | ||||
|                 T.Type = TOKEN_STRING; | ||||
|                 ++B->Ptr; | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 while(B->Ptr - B->Location < B->Size && *B->Ptr != '"') | ||||
|                 { | ||||
|                     if(*B->Ptr == '\\') | ||||
|                     { | ||||
|                         ++T.Content.Length; | ||||
|                         ++B->Ptr; | ||||
|                     } | ||||
|                     ++T.Content.Length; | ||||
|                     ++B->Ptr; | ||||
|                 } | ||||
|                 Advancement = 1; | ||||
|             } | ||||
|             else if(!StringsDifferS(TokenStrings[TOKEN_MINUS], B)) | ||||
|             { | ||||
|                 T.Type = TOKEN_MINUS; | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 ++T.Content.Length; | ||||
|                 Advancement = 1; | ||||
|             } | ||||
|             else if(!StringsDifferS(TokenStrings[TOKEN_ASSIGN], B)) | ||||
|             { | ||||
|                 T.Type = TOKEN_ASSIGN; | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 ++T.Content.Length; | ||||
|                 Advancement = 1; | ||||
|             } | ||||
|             else if(!StringsDifferS(TokenStrings[TOKEN_OPEN_BRACE], B)) | ||||
|             { | ||||
|                 T.Type = TOKEN_OPEN_BRACE; | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 ++T.Content.Length; | ||||
|                 Advancement = 1; | ||||
|             } | ||||
|             else if(!StringsDifferS(TokenStrings[TOKEN_CLOSE_BRACE], B)) | ||||
|             { | ||||
|                 T.Type = TOKEN_CLOSE_BRACE; | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 ++T.Content.Length; | ||||
|                 Advancement = 1; | ||||
|             } | ||||
|             else if(!StringsDifferS(TokenStrings[TOKEN_SEMICOLON], B)) | ||||
|             { | ||||
|                 T.Type = TOKEN_SEMICOLON; | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 ++T.Content.Length; | ||||
|                 Advancement = 1; | ||||
|             } | ||||
|             else if(IsValidIdentifierCharacter(*B->Ptr)) | ||||
|             { | ||||
|                 T.Type = TOKEN_IDENTIFIER; | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 while(IsValidIdentifierCharacter(*B->Ptr)) | ||||
|                 { | ||||
|                     ++T.Content.Length; | ||||
|                     ++B->Ptr; | ||||
|                 } | ||||
|                 Advancement = 0; | ||||
|             } | ||||
|             else if(IsNumber(*B->Ptr)) | ||||
|             { | ||||
|                 T.Type = TOKEN_NUMBER; | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 while(IsNumber(*B->Ptr)) | ||||
|                 { | ||||
|                     ++T.Content.Length; | ||||
|                     ++B->Ptr; | ||||
|                 } | ||||
|                 Advancement = 0; | ||||
|             } | ||||
|             else if(*B->Ptr == '\n') | ||||
|             { | ||||
|                 T.Type = TOKEN_NEWLINE; | ||||
|                 T.Content.Base = B->Ptr; | ||||
|                 T.Content.Length = 1; | ||||
|                 ++Result->CurrentLine; | ||||
|                 Advancement = 1; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 T.Type = TOKEN_NULL; | ||||
|                 string Char = GetUTF8Character(B->Ptr, B->Size - (B->Ptr - B->Location)); | ||||
|                 Advancement = Char.Length; | ||||
|                 string Filepath = Wrap0(Result->File.Path); | ||||
|                 if(Char.Base) | ||||
|                 { | ||||
|                     ConfigError(&Filepath, Result->CurrentLine, S_WARNING, "Unhandled character (ignored): ", &Char); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ConfigErrorInt(&Filepath, Result->CurrentLine, S_WARNING, "Malformed UTF-8 bytes encountered (skipped): ", Char.Length); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             PushToken(Result, &T); | ||||
|             Advance(B, Advancement); | ||||
|             SkipWhitespace(Result, B); | ||||
|         } | ||||
|                     PushToken(Result, &T); | ||||
|                     Advance(B, Advancement); | ||||
|                     SkipWhitespace(Result, B); | ||||
|                 } | ||||
|             } break; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         ConfigError(0, 0, S_WARNING, "Unable to open config file: ", &Path); | ||||
|     } | ||||
|     Free(Path0); | ||||
|     return Result; | ||||
| } | ||||
| 
 | ||||
|  | @ -2341,7 +2355,8 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T | |||
|                                                     } | ||||
|                                                     if(!I) | ||||
|                                                     { | ||||
|                                                         I = Tokenise(TokensList, IncludePathL); | ||||
|                                                         token *This = GetPlaceInBook(&T->Token, IncludePathTokenIndex); | ||||
|                                                         I = Tokenise(TokensList, IncludePathL, &Filepath, This->LineNumber); | ||||
|                                                     } | ||||
|                                                     if(I) | ||||
|                                                     { | ||||
|  | @ -2352,11 +2367,6 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T | |||
|                                                             return 0; | ||||
|                                                         } | ||||
|                                                     } | ||||
|                                                     else | ||||
|                                                     { | ||||
|                                                         token *This = GetPlaceInBook(&T->Token, IncludePathTokenIndex); | ||||
|                                                         ConfigFileIncludeError(&Filepath, This->LineNumber, Wrap0(IncludePath)); | ||||
|                                                     } | ||||
|                                                     Free(IncludePath); | ||||
|                                                 } | ||||
|                                                 else | ||||
|  | @ -4977,7 +4987,7 @@ ParseConfig(string Path, memory_book *TokensList) | |||
|         MEM_LOOP_POST("InitTypeSpecs") | ||||
| #endif | ||||
|     config *Result = 0; | ||||
|     tokens *T = Tokenise(TokensList, Path); | ||||
|     tokens *T = Tokenise(TokensList, Path, NA, NA); | ||||
| 
 | ||||
| #if 0 | ||||
|         MEM_LOOP_PRE_FREE("Tokenise") | ||||
|  | @ -4993,7 +5003,7 @@ ParseConfig(string Path, memory_book *TokensList) | |||
|         scope_tree *ScopeTree = InitRootScopeTree(); | ||||
|         SetTypeSpec(ScopeTree, &TypeSpecs); | ||||
|         SetDefaults(ScopeTree, &TypeSpecs); | ||||
|         ScopeTree = ScopeTokens(ScopeTree, TokensList, T, &TypeSpecs, 0); | ||||
|         ScopeTree = ScopeTokens(ScopeTree, TokensList, T, &TypeSpecs, NA); | ||||
| 
 | ||||
|         // TODO(matt): Mem testing
 | ||||
|         //
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue