refactor: move locking responsibility to user
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
2a373f3841
commit
088322c18f
6 changed files with 100 additions and 88 deletions
4
trie/README.md
Normal file
4
trie/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Trie design
|
||||
|
||||
This trie is a modified version of the custom trie I had to implement for my
|
||||
Algorithms & Datastructures 3 course.
|
||||
|
|
@ -94,7 +94,8 @@ bool trie_add_no_lock(Trie *trie, const char *key, Entry *entry);
|
|||
* @param trie
|
||||
* @param entry entry to add
|
||||
* @param secure whether to generate a longer, more secure random key
|
||||
* @return the generated key
|
||||
* @return pointer to the generated key. This pointer is safe to use after
|
||||
* unlocking the trie, and should be freed manually.
|
||||
*/
|
||||
char *trie_add_random(Trie *trie, Entry *entry, bool secure);
|
||||
|
||||
|
|
@ -116,4 +117,28 @@ bool trie_remove(Trie *trie, const char *key);
|
|||
*/
|
||||
size_t trie_size(Trie *trie);
|
||||
|
||||
/*
|
||||
* Acquire a read lock on the trie.
|
||||
*
|
||||
* @return 0 if successful, non-zero otherwise (return value of
|
||||
* pthread_rwlock_rdlock)
|
||||
*/
|
||||
int trie_rlock(Trie *trie);
|
||||
|
||||
/*
|
||||
* Acquire a write lock on the trie.
|
||||
*
|
||||
* @return 0 if successful, non-zero otherwise (return value of
|
||||
* pthread_rwlock_wrlock)
|
||||
*/
|
||||
int trie_wlock(Trie *trie);
|
||||
|
||||
/*
|
||||
* Release the lock on a trie after having acquired it beforehand.
|
||||
*
|
||||
* @return 0 if successful, non-zero otherwise (return value of
|
||||
* pthread_rwlock_unlock)
|
||||
*/
|
||||
int trie_unlock(Trie *trie);
|
||||
|
||||
#endif // AD3_TERNARYTRIE
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "trie.h"
|
||||
#include "trie_entry.c"
|
||||
#include "trie_node.c"
|
||||
|
||||
typedef struct ttrie {
|
||||
|
|
@ -39,41 +40,6 @@ void trie_free(Trie *trie) {
|
|||
|
||||
bool trie_add_no_lock(Trie *trie, const char *key, Entry *entry);
|
||||
|
||||
EntryType entry_type_from_char(char c) {
|
||||
switch (c) {
|
||||
case '0':
|
||||
return Redirect;
|
||||
case '1':
|
||||
return Paste;
|
||||
default:
|
||||
return Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
char entry_type_to_char(EntryType et) {
|
||||
switch (et) {
|
||||
case Redirect:
|
||||
return '0';
|
||||
case Paste:
|
||||
return '1';
|
||||
default:
|
||||
return '\0';
|
||||
}
|
||||
}
|
||||
|
||||
Entry *entry_new(EntryType type, const char *string) {
|
||||
Entry *entry = malloc(sizeof(Entry));
|
||||
entry->type = type;
|
||||
|
||||
if (string != NULL) {
|
||||
entry->string = strdup(string);
|
||||
} else {
|
||||
entry->string = NULL;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
int trie_populate(Trie *trie, const char *file_path) {
|
||||
trie->file_path = strdup(file_path);
|
||||
|
||||
|
|
@ -156,28 +122,6 @@ SearchResult trie_search_node(Trie *trie, const char *key) {
|
|||
|
||||
i += (*child_ptr)->string_len;
|
||||
|
||||
/* offset = 0; */
|
||||
|
||||
/* // We iterate over each character on the edge and compare it to the string. */
|
||||
/* while (offset < (*child_ptr)->string_len) { */
|
||||
/* // Our string ends in the middle of an edge, so it's definitely not in */
|
||||
/* // the trie. */
|
||||
/* if (key[i + offset] == DELIMITER) { */
|
||||
/* return out; */
|
||||
/* } */
|
||||
|
||||
/* // We compare each character with the characters in the skipped */
|
||||
/* // substring. If they don't match, we know the string isn't in the */
|
||||
/* // trie. */
|
||||
/* if (key[i + offset] != ((*child_ptr)->string[offset])) { */
|
||||
/* return out; */
|
||||
/* } */
|
||||
|
||||
/* offset++; */
|
||||
/* } */
|
||||
|
||||
/* i += offset; */
|
||||
|
||||
if (key[i] != DELIMITER) {
|
||||
node_ptr = child_ptr;
|
||||
}
|
||||
|
|
@ -202,8 +146,6 @@ SearchResult trie_search_node(Trie *trie, const char *key) {
|
|||
* @return true if the string is present in the trie, false otherwise
|
||||
*/
|
||||
Entry *trie_search(Trie *trie, const char *key) {
|
||||
pthread_rwlock_rdlock(&trie->lock);
|
||||
|
||||
SearchResult res = trie_search_node(trie, key);
|
||||
|
||||
Entry *return_value = NULL;
|
||||
|
|
@ -212,8 +154,6 @@ Entry *trie_search(Trie *trie, const char *key) {
|
|||
return_value = res.child->entry;
|
||||
}
|
||||
|
||||
pthread_rwlock_unlock(&trie->lock);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
|
|
@ -243,8 +183,7 @@ bool trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
|
|||
if (*child_node_ptr == NULL) {
|
||||
child_node = tnode_init();
|
||||
|
||||
while (offset < TRIE_MAX_SKIP_SIZE &&
|
||||
string[i + offset] != DELIMITER) {
|
||||
while (offset < TRIE_MAX_SKIP_SIZE && string[i + offset] != DELIMITER) {
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
|
@ -327,9 +266,7 @@ bool trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool trie_add_persistent(Trie *trie, const char *key, Entry *entry) {
|
||||
bool return_value = false;
|
||||
|
||||
bool 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
|
||||
// We use an internal function that doesn't require a read lock, as we're
|
||||
|
|
@ -350,8 +287,6 @@ bool trie_add_persistent(Trie *trie, const char *key, Entry *entry) {
|
|||
fputs(" ", fp);
|
||||
fputs(entry->string, fp);
|
||||
fputs("\n", fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
// This function *should* always return true. Otherwise, the function would've
|
||||
|
|
@ -359,19 +294,7 @@ bool trie_add_persistent(Trie *trie, const char *key, Entry *entry) {
|
|||
return trie_add_no_lock(trie, key, entry);
|
||||
}
|
||||
|
||||
bool trie_add(Trie *trie, const char *key, Entry *entry) {
|
||||
pthread_rwlock_wrlock(&trie->lock);
|
||||
|
||||
bool return_value = trie_add_persistent(trie, key, entry);
|
||||
|
||||
pthread_rwlock_unlock(&trie->lock);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
char *trie_add_random(Trie *trie, Entry *entry, bool secure) {
|
||||
pthread_rwlock_wrlock(&trie->lock);
|
||||
|
||||
// Generate random key
|
||||
bool ok = false;
|
||||
int key_length = secure ? RANDOM_KEY_LENGTH_LONG : RANDOM_KEY_LENGTH_SHORT;
|
||||
|
|
@ -389,7 +312,7 @@ char *trie_add_random(Trie *trie, Entry *entry, bool secure) {
|
|||
ok = trie_search_node(trie, key).child == NULL;
|
||||
}
|
||||
|
||||
bool res = trie_add_persistent(trie, key, entry);
|
||||
bool res = trie_add(trie, key, entry);
|
||||
char *return_value;
|
||||
|
||||
if (res) {
|
||||
|
|
@ -399,8 +322,6 @@ char *trie_add_random(Trie *trie, Entry *entry, bool secure) {
|
|||
free(key);
|
||||
}
|
||||
|
||||
pthread_rwlock_unlock(&trie->lock);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
|
|
@ -472,3 +393,12 @@ char *trie_add_random(Trie *trie, Entry *entry, bool secure) {
|
|||
* @return size of the trie
|
||||
*/
|
||||
size_t trie_size(Trie *trie) { return trie->size; }
|
||||
|
||||
int trie_rlock(Trie *trie) { return pthread_rwlock_rdlock(&trie->lock); }
|
||||
|
||||
int trie_wlock(Trie *trie) { return pthread_rwlock_wrlock(&trie->lock); }
|
||||
|
||||
int trie_unlock(Trie *trie) {
|
||||
printf("sup\n");
|
||||
return pthread_rwlock_unlock(&trie->lock);
|
||||
}
|
||||
|
|
|
|||
37
trie/src/trie_entry.c
Normal file
37
trie/src/trie_entry.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include "trie.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
EntryType entry_type_from_char(char c) {
|
||||
switch (c) {
|
||||
case '0':
|
||||
return Redirect;
|
||||
case '1':
|
||||
return Paste;
|
||||
default:
|
||||
return Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
char entry_type_to_char(EntryType et) {
|
||||
switch (et) {
|
||||
case Redirect:
|
||||
return '0';
|
||||
case Paste:
|
||||
return '1';
|
||||
default:
|
||||
return '\0';
|
||||
}
|
||||
}
|
||||
|
||||
Entry *entry_new(EntryType type, const char *string) {
|
||||
Entry *entry = malloc(sizeof(Entry));
|
||||
entry->type = type;
|
||||
|
||||
if (string != NULL) {
|
||||
entry->string = strdup(string);
|
||||
} else {
|
||||
entry->string = NULL;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue