Permalink
Browse files

Fix some memory leaks, add a NOTFOUND error code, and add CLEAR and D…

…ELETE
  • Loading branch information...
1 parent ff55af6 commit 592cacfe008087e017c10b8e82d742e85fbb4333 @txus committed Sep 21, 2012
Showing with 59 additions and 17 deletions.
  1. +2 −0 README.md
  2. +18 −7 src/shitdb/db.c
  3. +1 −0 src/shitdb/db.h
  4. +9 −3 src/shitdb/hashmap.c
  5. +3 −1 src/shitdb/hashmap.h
  6. +3 −0 src/shitdb/object.c
  7. +22 −5 src/shitdb/server.c
  8. +1 −1 tests/hashmap_tests.c
View
2 README.md
@@ -32,6 +32,8 @@ Example session:
* GET [key]: Returns the content of a key.
* SET [key] [value]: Sets key to a value of any of the basic types.
+* DELETE [key]: Deletes a key.
+* CLEAR: Clears all keys.
* QUIT: Ends the connection.
### Array commands
View
25 src/shitdb/db.c
@@ -3,29 +3,40 @@
#include <shitdb/hashmap.h>
#include <shitdb/db.h>
+static void destroy_object(void *obj)
+{
+ Object_destroy((Object*)obj);
+}
+
+static int destroy_object_node(HashmapNode *node)
+{
+ destroy_object((Object*)node);
+ return 0;
+}
+
DB*
DB_create()
{
DB *db = calloc(1, sizeof(DB));
check_mem(db);
- db->map = Hashmap_create(NULL, NULL);
+ db->map = Hashmap_create(NULL, NULL, destroy_object);
return db;
error:
return NULL;
}
-static int destroy_all(HashmapNode *node)
+void
+DB_clear(DB *db)
{
- Object_destroy((Object*)node);
- return 0;
+ Hashmap_traverse(db->map, destroy_object_node);
}
void
-DB_clear(DB *db)
+DB_delete(DB *db, bstring key)
{
- Hashmap_traverse(db->map, destroy_all);
+ Hashmap_delete(db->map, key);
}
void
@@ -85,7 +96,7 @@ DB_hset(DB *db, bstring key, bstring hkey, Object *value)
Object *hash = (Object*)Hashmap_get(db->map, key);
if (hash == NULL) {
- hash = Object_create_hash(Hashmap_create(NULL, NULL));
+ hash = Object_create_hash(Hashmap_create(NULL, NULL, destroy_object));
Hashmap_set(db->map, key, hash);
}
View
1 src/shitdb/db.h
@@ -13,6 +13,7 @@ DB* DB_create();
#define DB_destroy(db) Hashmap_destroy(db->map); free(db);
void DB_set(DB *db, bstring key, Object *value);
Object* DB_get(DB *db, bstring key);
+void DB_delete(DB *db, bstring key);
void DB_clear(DB *db);
// Array
View
12 src/shitdb/hashmap.c
@@ -14,6 +14,11 @@ static int default_compare(void *a, void *b)
return bstrcmp((bstring)a, (bstring)b);
}
+static void default_destroy(void *node)
+{
+ free(node);
+}
+
static uint32_t default_hash(void *a)
{
size_t len = blength((bstring)a);
@@ -35,13 +40,14 @@ static uint32_t default_hash(void *a)
return hash;
}
-Hashmap *Hashmap_create(Hashmap_compare compare, Hashmap_hash hash)
+Hashmap *Hashmap_create(Hashmap_compare compare, Hashmap_hash hash, Hashmap_destroy_cb destroy)
{
Hashmap *map = calloc(1, sizeof(Hashmap));
check_mem(map);
map->compare = compare == NULL ? default_compare : compare;
map->hash = hash == NULL ? default_hash : hash;
+ map->destroy = destroy == NULL ? default_destroy : destroy;
map->buckets = DArray_create(sizeof(DArray *), DEFAULT_NUMBER_OF_BUCKETS);
map->buckets->end = map->buckets->max;
check_mem(map->buckets);
@@ -67,7 +73,7 @@ void Hashmap_destroy(Hashmap *map)
DArray *bucket = DArray_get(map->buckets, i);
if(bucket) {
for(j = 0; j < DArray_count(bucket); j++) {
- free(DArray_get(bucket, j));
+ map->destroy(DArray_get(bucket, j));
}
DArray_destroy(bucket);
}
@@ -197,7 +203,7 @@ void *Hashmap_delete(Hashmap *map, void *key)
HashmapNode *node = DArray_get(bucket, i);
void *data = node->data;
- free(node);
+ map->destroy(node);
HashmapNode *ending = DArray_pop(bucket);
if(ending != node) {
View
4 src/shitdb/hashmap.h
@@ -8,11 +8,13 @@
typedef int (*Hashmap_compare)(void *a, void *b);
typedef uint32_t (*Hashmap_hash)(void *key);
+typedef void (*Hashmap_destroy_cb)(void *node);
typedef struct Hashmap {
DArray *buckets;
Hashmap_compare compare;
Hashmap_hash hash;
+ Hashmap_destroy_cb destroy;
} Hashmap;
typedef struct HashmapNode {
@@ -23,7 +25,7 @@ typedef struct HashmapNode {
typedef int (*Hashmap_traverse_cb)(HashmapNode *node);
-Hashmap *Hashmap_create(Hashmap_compare compare, Hashmap_hash);
+Hashmap *Hashmap_create(Hashmap_compare, Hashmap_hash, Hashmap_destroy_cb);
void Hashmap_destroy(Hashmap *map);
int Hashmap_set(Hashmap *map, void *key, void *data);
View
3 src/shitdb/object.c
@@ -30,6 +30,9 @@ Object_destroy(Object *object)
}
break;
}
+ case tHash: {
+ Hashmap_destroy(object->value.as_hash);
+ }
default:
break;
}
View
27 src/shitdb/server.c
@@ -15,6 +15,8 @@ int Command_arity(bstring cmd)
return 1;
} else if (eql(cmd, "SET")) {
return 2;
+ } else if (eql(cmd, "DELETE")) {
+ return 1;
} else if (eql(cmd, "APUSH")) {
return 2;
} else if (eql(cmd, "APOP")) {
@@ -52,14 +54,20 @@ int Server_execute(DB *db, bstring command, Object *result)
if(eql(cmd, "GET")) {
Object *ret = DB_get(db, *ptr);
- memcpy(result, ret, sizeof(Object));
+ if (ret) {
+ memcpy(result, ret, sizeof(Object));
+ } else {
+ return 2;
+ }
} else if (eql(cmd, "SET")) {
bstring key = *ptr;
ptr++;
Object *value = String_to_object(*ptr);
check(value, "Invalid value to SET.");
DB_set(db, key, value);
+ } else if (eql(cmd, "DELETE")) {
+ DB_delete(db, *ptr);
} else if (eql(cmd, "APUSH")) {
bstring key = *ptr;
ptr++;
@@ -73,8 +81,11 @@ int Server_execute(DB *db, bstring command, Object *result)
int index = atoi(bdata(*ptr));
Object *ret = DB_aat(db, key, index);
-
- memcpy(result, ret, sizeof(Object));
+ if (ret) {
+ memcpy(result, ret, sizeof(Object));
+ } else {
+ return 2;
+ }
} else if (eql(cmd, "ACOUNT")) {
bstring key = *ptr;
Object *ret = DB_acount(db, key);
@@ -84,7 +95,11 @@ int Server_execute(DB *db, bstring command, Object *result)
ptr++;
Object *ret = DB_apop(db, key);
- memcpy(result, ret, sizeof(Object));
+ if (ret) {
+ memcpy(result, ret, sizeof(Object));
+ } else {
+ return 2;
+ }
} else if (eql(cmd, "HSET")) {
bstring key = *ptr;
ptr++;
@@ -193,8 +208,10 @@ void Server_start(DB *db, int port)
}
} else if (rc == 1) {
send(accept_fd, "ERROR\n", 7, 0);
+ } else if (rc == 2) {
+ send(accept_fd, "NOTFOUND\n", 10, 0);
} else if (rc == -1) {
- send(accept_fd, "Bye!\n", 6, 0);
+ send(accept_fd, "BYE\n", 5, 0);
// Close the connection
close(accept_fd);
goto again;
View
2 tests/hashmap_tests.c
@@ -33,7 +33,7 @@ static int traverse_fail_cb(HashmapNode *node)
char *test_create()
{
- map = Hashmap_create(NULL, NULL);
+ map = Hashmap_create(NULL, NULL, NULL);
mu_assert(map != NULL, "Failed to create map.");
return NULL;

0 comments on commit 592cacf

Please sign in to comment.