aboutsummaryrefslogtreecommitdiffstats
path: root/src/mysqlerl.c
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2008-03-01 13:10:46 -0500
committerBrian Cully <bjc@kublai.com>2008-03-01 13:10:46 -0500
commit8ffa0cdb1f19cd56d7adf63893e5d158daa9aa3c (patch)
treef304bbcc3543be536089fafcad2fa4d3fc2fbd5f /src/mysqlerl.c
downloadmysqlerl-8ffa0cdb1f19cd56d7adf63893e5d158daa9aa3c.tar.gz
mysqlerl-8ffa0cdb1f19cd56d7adf63893e5d158daa9aa3c.zip
Initial commit
Diffstat (limited to 'src/mysqlerl.c')
-rw-r--r--src/mysqlerl.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/mysqlerl.c b/src/mysqlerl.c
new file mode 100644
index 0000000..d65dba1
--- /dev/null
+++ b/src/mysqlerl.c
@@ -0,0 +1,190 @@
+#include <mysql.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+const char *LOGPATH = "/tmp/mysqlerl.log";
+const size_t BUFSIZE = 2048;
+static FILE *logfile = NULL;
+
+typedef u_int32_t msglen_t;
+
+void
+openlog()
+{
+ logfile = fopen(LOGPATH, "a");
+}
+
+void
+closelog()
+{
+ fclose(logfile);
+}
+
+void
+logmsg(const char *format, ...)
+{
+ FILE *out = logfile;
+ va_list args;
+
+ if (logfile == NULL)
+ logfile = stderr;
+
+ va_start(args, format);
+ (void)vfprintf(logfile, format, args);
+ (void)fprintf(logfile, "\n");
+ va_end(args);
+
+ fflush(logfile);
+}
+
+int
+restartable_read(char *buf, size_t buflen)
+{
+ ssize_t rc, readb;
+
+ rc = 0;
+ READLOOP:
+ while (rc < buflen) {
+ readb = read(STDIN_FILENO, buf + rc, buflen - rc);
+ if (readb == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto READLOOP;
+
+ return -1;
+ } else if (readb == 0) {
+ logmsg("ERROR: EOF trying to read additional %d bytes from "
+ "standard input", buflen - rc);
+ return -1;
+ }
+
+ rc += readb;
+ }
+
+ return rc;
+}
+
+int
+restartable_write(const char *buf, size_t buflen)
+{
+ ssize_t rc, wroteb;
+
+ rc = 0;
+ WRITELOOP:
+ while (rc < buflen) {
+ wroteb = write(STDOUT_FILENO, buf + rc, buflen - rc);
+ if (wroteb == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto WRITELOOP;
+
+ return -1;
+ }
+
+ rc += wroteb;
+ }
+
+ return rc;
+}
+
+char *
+read_cmd()
+{
+ char *buf;
+ msglen_t len;
+
+ logmsg("DEBUG: reading message length.");
+ if (restartable_read((char *)&len, sizeof(len)) == -1) {
+ logmsg("ERROR: couldn't read %d byte message prefix: %s.",
+ sizeof(len), strerror(errno));
+ exit(2);
+ }
+ len = ntohl(len);
+
+ buf = malloc(len);
+ if (buf == NULL) {
+ logmsg("ERROR: Couldn't malloc %d bytes: %s.", len,
+ strerror(errno));
+ exit(2);
+ }
+ memset(buf, 0, BUFSIZE);
+
+ logmsg("DEBUG: reading message body (len: %d).", len);
+ if (restartable_read(buf, len) == -1) {
+ logmsg("ERROR: couldn't read %d byte message: %s.",
+ len, strerror(errno));
+ exit(2);
+ }
+
+ return buf;
+}
+
+int
+write_cmd(const char *cmd, msglen_t len)
+{
+ msglen_t nlen;
+
+ nlen = htonl(len + 3);
+ restartable_write((char *)&nlen, sizeof(nlen));
+ restartable_write(" - ", 3);
+ restartable_write(cmd, len);
+}
+
+void
+dispatch_db_cmd(MYSQL *dbh, const char *cmd)
+{
+ msglen_t len, nlen;
+
+ logmsg("DEBUG: dispatch_cmd(\"%s\")", cmd);
+ write_cmd(cmd, strlen(cmd));
+}
+
+void
+usage()
+{
+ fprintf(stderr, "Usage: mysqlerl host port db_name user passwd\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ MYSQL dbh;
+ char *host, *port, *db_name, *user, *passwd, *cmd;
+
+ openlog();
+ logmsg("INFO: starting up.");
+
+ if (argc < 6)
+ usage();
+
+ host = argv[1];
+ port = argv[2];
+ db_name = argv[3];
+ user = argv[4];
+ passwd = argv[5];
+
+ mysql_init(&dbh);
+ if (mysql_real_connect(&dbh, host, user, passwd,
+ db_name, atoi(port), NULL, 0) == NULL) {
+ logmsg("ERROR: Failed to connect to database %s: %s (%s:%s).",
+ db_name, mysql_error(&dbh), user, passwd);
+ exit(2);
+ }
+
+ while ((cmd = read_cmd()) != NULL) {
+ dispatch_db_cmd(&dbh, cmd);
+ free(cmd);
+ }
+
+ mysql_close(&dbh);
+
+ logmsg("INFO: shutting down.");
+ closelog();
+
+ return 0;
+}