Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fixed a couple of memory leaks that were causing seg faults and added…

… a threaded signal handler to allow for in place load of a snapshot file
  • Loading branch information...
commit 3c542592f6e2efce52bd59687cc408ad7dc9f154 1 parent 1549776
@dwayn dwayn authored
Showing with 68 additions and 33 deletions.
  1. +52 −11 src/barbershop.c
  2. +1 −0  src/barbershop.h
  3. +9 −2 src/pqueue.c
  4. +6 −20 src/pqueue.h
View
63 src/barbershop.c
@@ -45,6 +45,8 @@ THE SOFTWARE.
#include <event.h>
#include "commands.h"
+volatile sig_atomic_t respond_empty = 0;
+
void on_read(int fd, short ev, void *arg)
{
struct client *client = (struct client *)arg;
@@ -62,6 +64,11 @@ void on_read(int fd, short ev, void *arg)
free(client);
return;
}
+ if(respond_empty == 1)
+ {
+ reply(fd, "-1\r\n");
+ return;
+ }
process_request(fd, buf);
}
@@ -135,18 +142,30 @@ int main(int argc, char **argv)
sync_file = "barbershop.snapshot";
}
+ // side snapshot file to hot load a snapshot by sending SIGHUP
+ int n = strlen(sync_file);
+ load_file = malloc(sizeof(char) * (n + 6));
+ sprintf(load_file, "%s.load", sync_file);
+
initializePriorityQueue();
-
- load_snapshot(sync_file);
time(&app_stats.started_at);
- app_stats.version = "00.01.00";
+ app_stats.version = "00.02.01";
app_stats.updates = 0;
app_stats.items = 0;
app_stats.pools = 0;
+ load_snapshot(sync_file);
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGHUP, signal_handler); /* catch hangup signal */
+ signal(SIGTERM, signal_handler); /* catch kill signal */
+
pthread_t garbage_collector;
- pthread_create(&garbage_collector, NULL, (void *) gc_thread, NULL);
+ pthread_create(&garbage_collector, NULL, (void *) gc_thread, NULL);
int listen_fd;
struct sockaddr_in listen_addr;
@@ -195,12 +214,32 @@ void gc_thread()
pthread_exit(0);
}
+void snap_thread()
+{
+ load_snapshot(load_file);
+ respond_empty = 0;
+ pthread_exit(0);
+}
+
+void write_thread()
+{
+ pthread_mutex_lock(&scores_mutex);
+ sync_to_disk(sync_file);
+ pthread_mutex_unlock(&scores_mutex);
+ respond_empty = 0;
+ exit(0);
+}
+
void load_snapshot(char *filename)
{
+ respond_empty = 1;
+ pthread_mutex_lock(&scores_mutex);
+ emptyPriorityQueue();
FILE *file_in;
file_in = fopen(filename, "r");
if (file_in == NULL)
{
+ pthread_mutex_unlock(&scores_mutex);
return;
}
char line[80];
@@ -208,15 +247,11 @@ void load_snapshot(char *filename)
while(fgets(line, 80, file_in) != NULL)
{
sscanf(line, "%d %d", &item_id, &score);
- pthread_mutex_lock(&scores_mutex);
int success = update(item_id, score);
- if(success >= 0)
- app_stats.updates += 1;
- if(success == 1);
- app_stats.items += 1;
- pthread_mutex_unlock(&scores_mutex);
}
fclose(file_in);
+ pthread_mutex_unlock(&scores_mutex);
+ respond_empty = 0;
}
void sync_to_disk(char *filename)
@@ -284,11 +319,17 @@ void daemonize()
// TODO: on SIGTERM exit.
void signal_handler(int sig)
{
+ pthread_t sig_thread;
switch(sig) {
case SIGHUP:
+ respond_empty = 1;
+ pthread_create(&sig_thread, NULL, (void *) snap_thread, NULL);
+ signal(SIGHUP, signal_handler); /* catch hangup signal */
break;
case SIGTERM:
- exit(0);
+ respond_empty = 1;
+ pthread_create(&sig_thread, NULL, (void *) write_thread, NULL);
+ signal(SIGTERM, signal_handler); /* catch hangup signal */
break;
}
}
View
1  src/barbershop.h
@@ -37,6 +37,7 @@ struct client {
pthread_mutex_t scores_mutex;
int timeout;
char *sync_file;
+char *load_file;
int main(int argc, char **argv);
View
11 src/pqueue.c
@@ -60,6 +60,13 @@ int getNext()
return rval;
}
+void emptyPriorityQueue()
+{
+ int r = getNext();
+ while(r > -1)
+ r = getNext();
+}
+
int getScore(int itemId)
{
ItemTreeNode itnode = findItem(itemId, item_root);
@@ -186,6 +193,7 @@ ItemNode createItemNode(int id)
node->itemId = id;
node->next = NULL;
node->prev = NULL;
+ app_stats.items += 1;
return node;
}
ItemTreeNode createItemTreeNode()
@@ -240,7 +248,6 @@ ItemTreeNode addItemTreeNode(ItemTreeNode tree, ItemTreeNode node)
if(tree == NULL)
{
tree = node;
- app_stats.items += 1;
}
else
{
@@ -261,6 +268,7 @@ void deleteItemNode(ItemNode i)
{
if(i->next == NULL && i->prev == NULL)
{
+ app_stats.items -= 1;
free(i);
}
else
@@ -343,7 +351,6 @@ ItemTreeNode deleteItemTreeNode(ItemTreeNode tree, ItemTreeNode node)
tree = tree->left;
}
free(TmpCell);
- app_stats.items -= 1;
}
return tree;
View
26 src/pqueue.h
@@ -1,24 +1,9 @@
/*
-Copyright (c) 2010 Dwayn Matthies <dwayn(dot)matthies(at)gmail(dot)com>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
+ * File: pqueue.h
+ * Author: dwayn
+ *
+ * Created on June 25, 2010, 11:45 PM
+ */
#ifndef _PQUEUE_H
#define _PQUEUE_H
@@ -75,6 +60,7 @@ int update(int itemId, int score);
void outputScores(FILE *fd);
void outputScoresIterator(FILE *fd, ScoreTreeNode tree);
void initializePriorityQueue();
+void emptyPriorityQueue();
void dumpItems();
void dumpItemsIterator(ItemTreeNode tree);
Please sign in to comment.
Something went wrong with that request. Please try again.