refactor: started refactoring trie api (contains segfaults)
							parent
							
								
									088322c18f
								
							
						
					
					
						commit
						50ebf86589
					
				|  | @ -4,7 +4,7 @@ project(lander C CXX) | ||||||
| set(CMAKE_C_STANDARD 17) | set(CMAKE_C_STANDARD 17) | ||||||
| set(CMAKE_CXX_STANDARD 17) | set(CMAKE_CXX_STANDARD 17) | ||||||
| 
 | 
 | ||||||
| include_directories(crow/include trie/include) | include_directories(trie/include) | ||||||
| add_subdirectory(crow) | add_subdirectory(crow) | ||||||
| add_subdirectory(trie) | add_subdirectory(trie) | ||||||
| 
 | 
 | ||||||
|  | @ -16,5 +16,5 @@ else() | ||||||
|     endif() |     endif() | ||||||
| 
 | 
 | ||||||
|     add_executable(lander src/main.cpp) |     add_executable(lander src/main.cpp) | ||||||
|     target_link_libraries(lander PUBLIC trie) |     target_link_libraries(lander PUBLIC Crow::Crow trie) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
							
								
								
									
										60
									
								
								src/main.cpp
								
								
								
								
							
							
						
						
									
										60
									
								
								src/main.cpp
								
								
								
								
							|  | @ -7,6 +7,7 @@ extern "C" { | ||||||
| #include "trie.h" | #include "trie.h" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const std::string file_path = "lander.data"; | ||||||
| static const std::string index_page = R"( | static const std::string index_page = R"( | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html> | <html> | ||||||
|  | @ -38,17 +39,18 @@ crow::response add_redirect(std::string base_url, Trie *trie, const char *url, | ||||||
|   // The key already gets copied into the trie, so this pointer is safe to use
 |   // The key already gets copied into the trie, so this pointer is safe to use
 | ||||||
|   // ever after unlocking the trie
 |   // ever after unlocking the trie
 | ||||||
|   trie_wlock(trie); |   trie_wlock(trie); | ||||||
|   char *key = trie_add_random(trie, new_entry, secure); |   char *key; | ||||||
|  |   TrieExitCode res = trie_add_random(trie, &key, new_entry, secure); | ||||||
|   trie_unlock(trie); |   trie_unlock(trie); | ||||||
| 
 | 
 | ||||||
|   if (key == NULL) { |   if (res != Ok) { | ||||||
|     return crow::response(crow::status::INTERNAL_SERVER_ERROR); |     return crow::response(crow::status::INTERNAL_SERVER_ERROR); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   std::string res = base_url + key; |   std::string out = base_url + key; | ||||||
|   free(key); |   free(key); | ||||||
| 
 | 
 | ||||||
|   return crow::response(res); |   return crow::response(out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool store_paste(const char *key, const char *body) { | bool store_paste(const char *key, const char *body) { | ||||||
|  | @ -71,10 +73,11 @@ crow::response add_paste(std::string base_url, Trie *trie, const char *body, | ||||||
|   Entry *new_entry = entry_new(Paste, ""); |   Entry *new_entry = entry_new(Paste, ""); | ||||||
| 
 | 
 | ||||||
|   trie_wlock(trie); |   trie_wlock(trie); | ||||||
|   char *key = trie_add_random(trie, new_entry, secure); |   char *key; | ||||||
|  |   TrieExitCode res = trie_add_random(trie, &key, new_entry, secure); | ||||||
|   trie_unlock(trie); |   trie_unlock(trie); | ||||||
| 
 | 
 | ||||||
|   if (key == NULL) { |   if (res != Ok) { | ||||||
|     return crow::response(crow::status::INTERNAL_SERVER_ERROR); |     return crow::response(crow::status::INTERNAL_SERVER_ERROR); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -82,10 +85,10 @@ crow::response add_paste(std::string base_url, Trie *trie, const char *body, | ||||||
|     return crow::response(crow::status::INTERNAL_SERVER_ERROR); |     return crow::response(crow::status::INTERNAL_SERVER_ERROR); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   std::string res = base_url + key; |   std::string out = base_url + key; | ||||||
|   free(key); |   free(key); | ||||||
| 
 | 
 | ||||||
|   return crow::response(res); |   return crow::response(out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main() { | int main() { | ||||||
|  | @ -95,26 +98,21 @@ int main() { | ||||||
|   ENV(api_key, "LANDER_API_KEY"); |   ENV(api_key, "LANDER_API_KEY"); | ||||||
|   ENV(base_url, "LANDER_BASE_URL"); |   ENV(base_url, "LANDER_BASE_URL"); | ||||||
| 
 | 
 | ||||||
|   // Initialize trie and populate from data file
 |   std::cout << "Initializing trie from file '" << file_path << "'..." | ||||||
|   Trie *trie = trie_init(); |  | ||||||
| 
 |  | ||||||
|   std::string file_path = "lander.data"; |  | ||||||
| 
 |  | ||||||
|   std::cout << "Populating trie from file '" << file_path << "'..." |  | ||||||
|             << std::endl; |             << std::endl; | ||||||
| 
 | 
 | ||||||
|   // Web server hasn't started yet, so there's no point in locking the trie
 |   // Initialize trie and populate from data file
 | ||||||
|   int count = trie_populate(trie, file_path.c_str()); |   Trie *trie; | ||||||
|  |   int res = trie_init(&trie, file_path.c_str()); | ||||||
| 
 | 
 | ||||||
|   if (count == -1) { |   if (res != 0) { | ||||||
|     std::cout << "An error occured while populating the trie." << std::endl; |     std::cout << "An error occured while initializing the trie." << std::endl; | ||||||
| 
 | 
 | ||||||
|     exit(1); |     exit(1); | ||||||
|   } else { |  | ||||||
|     std::cout << "Added " << count << " (" << trie_size(trie) |  | ||||||
|               << ") entries to trie." << std::endl; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   std::cout << "Added " << trie_size(trie) << " entries to trie." << std::endl; | ||||||
|  | 
 | ||||||
|   // Create pastes directory if not present
 |   // Create pastes directory if not present
 | ||||||
|   // TODO don't just ignore errors here
 |   // TODO don't just ignore errors here
 | ||||||
|   mkdir("pastes", 0700); |   mkdir("pastes", 0700); | ||||||
|  | @ -130,9 +128,10 @@ int main() { | ||||||
|       .methods(crow::HTTPMethod::Get)( |       .methods(crow::HTTPMethod::Get)( | ||||||
|           [trie](crow::response &res, std::string key) { |           [trie](crow::response &res, std::string key) { | ||||||
|             trie_rlock(trie); |             trie_rlock(trie); | ||||||
|             Entry *entry = trie_search(trie, key.c_str()); |             Entry *entry; | ||||||
|  |             TrieExitCode status = trie_search(trie, &entry, key.c_str()); | ||||||
| 
 | 
 | ||||||
|             if (entry != NULL) { |             if (status == Ok) { | ||||||
|               if (entry->type == Redirect) { |               if (entry->type == Redirect) { | ||||||
|                 res.redirect(entry->string); |                 res.redirect(entry->string); | ||||||
|               } else if (entry->type == Paste) { |               } else if (entry->type == Paste) { | ||||||
|  | @ -173,14 +172,17 @@ int main() { | ||||||
|             Entry *new_entry = entry_new(Redirect, req.body.c_str()); |             Entry *new_entry = entry_new(Redirect, req.body.c_str()); | ||||||
| 
 | 
 | ||||||
|             trie_wlock(trie); |             trie_wlock(trie); | ||||||
|             bool added = trie_add(trie, key.c_str(), new_entry); |             TrieExitCode status = trie_add(trie, key.c_str(), new_entry); | ||||||
|             trie_unlock(trie); |             trie_unlock(trie); | ||||||
| 
 | 
 | ||||||
|             if (!added) { |             switch (status) { | ||||||
|  |             case Ok: | ||||||
|  |               return crow::response(base_url + key); | ||||||
|  |             case AlreadyPresent: | ||||||
|               return crow::response(crow::status::CONFLICT); |               return crow::response(crow::status::CONFLICT); | ||||||
|  |             default: | ||||||
|  |               return crow::response(crow::status::INTERNAL_SERVER_ERROR); | ||||||
|             } |             } | ||||||
| 
 |  | ||||||
|             return crow::response(base_url + key); |  | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|   // Add a new Paste with a short randomly generated key
 |   // Add a new Paste with a short randomly generated key
 | ||||||
|  | @ -209,10 +211,10 @@ int main() { | ||||||
| 
 | 
 | ||||||
|             Entry *new_entry = entry_new(Paste, ""); |             Entry *new_entry = entry_new(Paste, ""); | ||||||
|             trie_wlock(trie); |             trie_wlock(trie); | ||||||
|             bool added = trie_add(trie, key.c_str(), new_entry); |             TrieExitCode status = trie_add(trie, key.c_str(), new_entry); | ||||||
|             trie_unlock(trie); |             trie_unlock(trie); | ||||||
| 
 | 
 | ||||||
|             if (!added) { |             if (status != Ok) { | ||||||
|               return crow::response(crow::status::CONFLICT); |               return crow::response(crow::status::CONFLICT); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -41,23 +41,22 @@ typedef struct entry { | ||||||
|   char *string; |   char *string; | ||||||
| } Entry; | } Entry; | ||||||
| 
 | 
 | ||||||
|  | typedef enum trie_exit_code { | ||||||
|  |   Ok = 0, | ||||||
|  |   NotFound, | ||||||
|  |   AlreadyPresent, | ||||||
|  |   FileError | ||||||
|  | } TrieExitCode; | ||||||
|  | 
 | ||||||
| Entry *entry_new(EntryType type, const char *string); | Entry *entry_new(EntryType type, const char *string); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Allocate and initialize an empty Trie. |  * Allocate & initialize a new trie, and populate it with the data from the | ||||||
|  |  * given data file. | ||||||
|  * |  * | ||||||
|  * @return a pointer to an empty Trie struct |  * @return 0 if everything was successful, non-zero otherwise | ||||||
|  */ |  */ | ||||||
| Trie *trie_init(); | TrieExitCode trie_init(Trie **trie_ptr, const char *file_path); | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Populate trie with entries stored in the given file. |  | ||||||
|  * |  | ||||||
|  * @param trie |  | ||||||
|  * @param file_path path to file containing entries |  | ||||||
|  * @return amount of entries added; -1 if an error occured |  | ||||||
|  */ |  | ||||||
| int trie_populate(Trie *trie, const char *file_path); |  | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * De-allocate a trie by freeing the memory occupied by this trie. |  * De-allocate a trie by freeing the memory occupied by this trie. | ||||||
|  | @ -70,10 +69,11 @@ void trie_free(Trie *trie); | ||||||
|  * Search for an entry in the trie. |  * Search for an entry in the trie. | ||||||
|  * |  * | ||||||
|  * @param trie |  * @param trie | ||||||
|  |  * @param entry_ptr pointer to Entry will be stored here, if found | ||||||
|  * @param key key representing the entry |  * @param key key representing the entry | ||||||
|  * @return pointer to entry; NULL if not found |  * @return 0 if the search was successful, 1 if not found | ||||||
|  */ |  */ | ||||||
| Entry *trie_search(Trie *trie, const char *key); | TrieExitCode trie_search(Trie *trie, Entry **entry_ptr, const char *key); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Add a string to this trie. |  * Add a string to this trie. | ||||||
|  | @ -81,12 +81,9 @@ Entry *trie_search(Trie *trie, const char *key); | ||||||
|  * @param trie |  * @param trie | ||||||
|  * @param key key to represent entry with |  * @param key key to represent entry with | ||||||
|  * @param entry entry to add |  * @param entry entry to add | ||||||
|  * @return true if the trie was changed by this operation, false if it was |  * @return 0 if added, 1 if already in trie, something else if other errors | ||||||
|  * already present |  | ||||||
|  */ |  */ | ||||||
| bool trie_add(Trie *trie, const char *key, Entry *entry); | TrieExitCode trie_add(Trie *trie, const char *key, Entry *entry); | ||||||
| 
 |  | ||||||
| bool trie_add_no_lock(Trie *trie, const char *key, Entry *entry); |  | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Add an entry by generating a random string as the key. |  * Add an entry by generating a random string as the key. | ||||||
|  | @ -97,7 +94,8 @@ bool trie_add_no_lock(Trie *trie, const char *key, Entry *entry); | ||||||
|  * @return pointer to the generated key. This pointer is safe to use after |  * @return pointer to the generated key. This pointer is safe to use after | ||||||
|  * unlocking the trie, and should be freed manually. |  * unlocking the trie, and should be freed manually. | ||||||
|  */ |  */ | ||||||
| char *trie_add_random(Trie *trie, Entry *entry, bool secure); | TrieExitCode trie_add_random(Trie *trie, char **key_ptr, Entry *entry, | ||||||
|  |                              bool secure); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Remove an entry from this trie given its key. |  * Remove an entry from this trie given its key. | ||||||
|  |  | ||||||
							
								
								
									
										122
									
								
								trie/src/trie.c
								
								
								
								
							
							
						
						
									
										122
									
								
								trie/src/trie.c
								
								
								
								
							|  | @ -15,39 +15,25 @@ typedef struct ttrie { | ||||||
|   pthread_rwlock_t lock; |   pthread_rwlock_t lock; | ||||||
| } Trie; | } Trie; | ||||||
| 
 | 
 | ||||||
|  | TrieExitCode trie_add_no_lock(Trie *trie, const char *key, Entry *entry); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Allocate and initialize an empty Trie |  * Allocate and initialize an empty Trie | ||||||
|  * |  * | ||||||
|  * @return pointer to the empty Trie |  * @return pointer to the empty Trie | ||||||
|  */ |  */ | ||||||
| Trie *trie_init() { | TrieExitCode trie_init(Trie **trie_ptr, const char *file_path) { | ||||||
|  |   // Allocate & initialize trie
 | ||||||
|   Trie *trie = calloc(1, sizeof(Trie)); |   Trie *trie = calloc(1, sizeof(Trie)); | ||||||
|   trie->root = tnode_init(); |   trie->root = tnode_init(); | ||||||
|  |   trie->file_path = strdup(file_path); | ||||||
|   pthread_rwlock_init(&trie->lock, NULL); |   pthread_rwlock_init(&trie->lock, NULL); | ||||||
| 
 | 
 | ||||||
|   return trie; |   // Populate trie with data from file
 | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * De-allocate a TernaryTree by freeing its entire underlying structure. |  | ||||||
|  * |  | ||||||
|  * @param trie trie to free |  | ||||||
|  */ |  | ||||||
| void trie_free(Trie *trie) { |  | ||||||
|   tnode_free(trie->root); |  | ||||||
|   free(trie); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool trie_add_no_lock(Trie *trie, const char *key, Entry *entry); |  | ||||||
| 
 |  | ||||||
| int trie_populate(Trie *trie, const char *file_path) { |  | ||||||
|   trie->file_path = strdup(file_path); |  | ||||||
| 
 |  | ||||||
|   FILE *fp = fopen(file_path, "r"); |   FILE *fp = fopen(file_path, "r"); | ||||||
| 
 | 
 | ||||||
|   // TODO properly handle this
 |  | ||||||
|   if (fp == NULL) { |   if (fp == NULL) { | ||||||
|     return -1; |     return FileError; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // We read in lines of at most 8192 characters (sounds like enough)
 |   // We read in lines of at most 8192 characters (sounds like enough)
 | ||||||
|  | @ -89,7 +75,19 @@ int trie_populate(Trie *trie, const char *file_path) { | ||||||
| 
 | 
 | ||||||
|   fclose(fp); |   fclose(fp); | ||||||
| 
 | 
 | ||||||
|   return entries; |   *trie_ptr = trie; | ||||||
|  | 
 | ||||||
|  |   return Ok; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * De-allocate a TernaryTree by freeing its entire underlying structure. | ||||||
|  |  * | ||||||
|  |  * @param trie trie to free | ||||||
|  |  */ | ||||||
|  | void trie_free(Trie *trie) { | ||||||
|  |   tnode_free(trie->root); | ||||||
|  |   free(trie); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| typedef struct searchresult { | typedef struct searchresult { | ||||||
|  | @ -145,16 +143,16 @@ SearchResult trie_search_node(Trie *trie, const char *key) { | ||||||
|  * @param string string to look up |  * @param string string to look up | ||||||
|  * @return true if the string is present in the trie, false otherwise |  * @return true if the string is present in the trie, false otherwise | ||||||
|  */ |  */ | ||||||
| Entry *trie_search(Trie *trie, const char *key) { | TrieExitCode trie_search(Trie *trie, Entry **entry_ptr, const char *key) { | ||||||
|   SearchResult res = trie_search_node(trie, key); |   SearchResult res = trie_search_node(trie, key); | ||||||
| 
 | 
 | ||||||
|   Entry *return_value = NULL; |   if (res.child == NULL) { | ||||||
| 
 |     return NotFound; | ||||||
|   if (res.child != NULL) { |  | ||||||
|     return_value = res.child->entry; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return return_value; |   *entry_ptr = res.child->entry; | ||||||
|  | 
 | ||||||
|  |   return Ok; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -165,7 +163,7 @@ Entry *trie_search(Trie *trie, const char *key) { | ||||||
|  * @return true if the string wasn't present in the trie and thus added, false |  * @return true if the string wasn't present in the trie and thus added, false | ||||||
|  * otherwise |  * otherwise | ||||||
|  */ |  */ | ||||||
| bool trie_add_no_lock(Trie *trie, const char *string, Entry *entry) { | TrieExitCode trie_add_no_lock(Trie *trie, const char *string, Entry *entry) { | ||||||
|   size_t i = 0; |   size_t i = 0; | ||||||
|   uint8_t offset; |   uint8_t offset; | ||||||
|   TrieNode **node_ptr = &(trie->root); |   TrieNode **node_ptr = &(trie->root); | ||||||
|  | @ -207,7 +205,7 @@ bool trie_add_no_lock(Trie *trie, const char *string, Entry *entry) { | ||||||
|       child_node->entry = entry; |       child_node->entry = entry; | ||||||
| 
 | 
 | ||||||
|       trie->size++; |       trie->size++; | ||||||
|       return true; |       return Ok; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     while (offset < (*child_node_ptr)->string_len) { |     while (offset < (*child_node_ptr)->string_len) { | ||||||
|  | @ -258,43 +256,44 @@ bool trie_add_no_lock(Trie *trie, const char *string, Entry *entry) { | ||||||
|   } while (string[i] != DELIMITER); |   } while (string[i] != DELIMITER); | ||||||
| 
 | 
 | ||||||
|   if ((*child_node_ptr)->represents) { |   if ((*child_node_ptr)->represents) { | ||||||
|     return false; |     return AlreadyPresent; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   (*child_node_ptr)->represents = true; |   (*child_node_ptr)->represents = true; | ||||||
|   trie->size++; |   trie->size++; | ||||||
|   return true; |   return Ok; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool trie_add(Trie *trie, const char *key, Entry *entry) { | TrieExitCode trie_add(Trie *trie, const char *key, Entry *entry) { | ||||||
|   if (trie->file_path != NULL) { |   // Easiest way to make sure we don't add duplicate entries
 | ||||||
|     // Easiest way to make sure we don't add duplicate entries
 |   // We use an internal function that doesn't require a read lock, as we're
 | ||||||
|     // We use an internal function that doesn't require a read lock, as we're
 |   // already inside a write lock
 | ||||||
|     // already inside a write lock
 |   if (trie_search_node(trie, key).child != NULL) { | ||||||
|     if (trie_search_node(trie, key).child != NULL) { |     return AlreadyPresent; | ||||||
|       return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     FILE *fp = fopen(trie->file_path, "a"); |  | ||||||
| 
 |  | ||||||
|     if (fp == NULL) { |  | ||||||
|       return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fputs(key, fp); |  | ||||||
|     fputs(" ", fp); |  | ||||||
|     fputc(entry_type_to_char(entry->type), fp); |  | ||||||
|     fputs(" ", fp); |  | ||||||
|     fputs(entry->string, fp); |  | ||||||
|     fputs("\n", fp); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // This function *should* always return true. Otherwise, the function would've
 |   FILE *fp = fopen(trie->file_path, "a"); | ||||||
|  | 
 | ||||||
|  |   if (fp == NULL) { | ||||||
|  |     return FileError; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   fputs(key, fp); | ||||||
|  |   fputs(" ", fp); | ||||||
|  |   fputc(entry_type_to_char(entry->type), fp); | ||||||
|  |   fputs(" ", fp); | ||||||
|  |   fputs(entry->string, fp); | ||||||
|  |   fputs("\n", fp); | ||||||
|  | 
 | ||||||
|  |   fclose(fp); | ||||||
|  | 
 | ||||||
|  |   // This function *should* always return Ok. Otherwise, the function would've
 | ||||||
|   // exited because the string was found in the trie.
 |   // exited because the string was found in the trie.
 | ||||||
|   return trie_add_no_lock(trie, key, entry); |   return trie_add_no_lock(trie, key, entry); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char *trie_add_random(Trie *trie, Entry *entry, bool secure) { | TrieExitCode trie_add_random(Trie *trie, char **key_ptr, Entry *entry, | ||||||
|  |                              bool secure) { | ||||||
|   // Generate random key
 |   // Generate random key
 | ||||||
|   bool ok = false; |   bool ok = false; | ||||||
|   int key_length = secure ? RANDOM_KEY_LENGTH_LONG : RANDOM_KEY_LENGTH_SHORT; |   int key_length = secure ? RANDOM_KEY_LENGTH_LONG : RANDOM_KEY_LENGTH_SHORT; | ||||||
|  | @ -312,13 +311,11 @@ char *trie_add_random(Trie *trie, Entry *entry, bool secure) { | ||||||
|     ok = trie_search_node(trie, key).child == NULL; |     ok = trie_search_node(trie, key).child == NULL; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   bool res = trie_add(trie, key, entry); |   TrieExitCode return_value = trie_add(trie, key, entry); | ||||||
|   char *return_value; |  | ||||||
| 
 | 
 | ||||||
|   if (res) { |   if (return_value == Ok) { | ||||||
|     return_value = key; |     *key_ptr = key; | ||||||
|   } else { |   } else { | ||||||
|     return_value = NULL; |  | ||||||
|     free(key); |     free(key); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -398,7 +395,4 @@ int trie_rlock(Trie *trie) { return pthread_rwlock_rdlock(&trie->lock); } | ||||||
| 
 | 
 | ||||||
| int trie_wlock(Trie *trie) { return pthread_rwlock_wrlock(&trie->lock); } | int trie_wlock(Trie *trie) { return pthread_rwlock_wrlock(&trie->lock); } | ||||||
| 
 | 
 | ||||||
| int trie_unlock(Trie *trie) { | int trie_unlock(Trie *trie) { return pthread_rwlock_unlock(&trie->lock); } | ||||||
|   printf("sup\n"); |  | ||||||
|   return pthread_rwlock_unlock(&trie->lock); |  | ||||||
| } |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue