ovsdb: Rename ovsdb_file to ovsdb_log.
authorBen Pfaff <blp@nicira.com>
Fri, 13 Nov 2009 21:23:35 +0000 (13:23 -0800)
committerBen Pfaff <blp@nicira.com>
Mon, 16 Nov 2009 18:55:27 +0000 (10:55 -0800)
This prepares for introducing a new, higher-level ovsdb_file that
encapsulates ovsdb storage in a file.

15 files changed:
lib/vlog-modules.def
ovsdb/automake.mk
ovsdb/execution.c
ovsdb/file.c [deleted file]
ovsdb/file.h [deleted file]
ovsdb/log.c [new file with mode: 0644]
ovsdb/log.h [new file with mode: 0644]
ovsdb/ovsdb-tool.c
ovsdb/ovsdb.c
ovsdb/ovsdb.h
tests/automake.mk
tests/ovsdb-file.at [deleted file]
tests/ovsdb-log.at [new file with mode: 0644]
tests/ovsdb.at
tests/test-ovsdb.c

index 5dc7745..24f62cc 100644 (file)
@@ -56,7 +56,7 @@ VLOG_MODULE(ofproto)
 VLOG_MODULE(openflowd)
 VLOG_MODULE(ovsdb)
 VLOG_MODULE(ovsdb_client)
-VLOG_MODULE(ovsdb_file)
+VLOG_MODULE(ovsdb_log)
 VLOG_MODULE(ovsdb_jsonrpc_server)
 VLOG_MODULE(ovsdb_server)
 VLOG_MODULE(ovsdb_tool)
index 04fa52d..b996a30 100644 (file)
@@ -6,10 +6,10 @@ ovsdb_libovsdb_a_SOURCES = \
        ovsdb/condition.c \
        ovsdb/condition.h \
        ovsdb/execution.c \
-       ovsdb/file.c \
-       ovsdb/file.h \
        ovsdb/jsonrpc-server.c \
        ovsdb/jsonrpc-server.h \
+       ovsdb/log.c \
+       ovsdb/log.h \
        ovsdb/ovsdb-server.c \
        ovsdb/ovsdb.c \
        ovsdb/ovsdb.h \
index f3e9172..6bad67c 100644 (file)
@@ -20,8 +20,8 @@
 
 #include "column.h"
 #include "condition.h"
-#include "file.h"
 #include "json.h"
+#include "log.h"
 #include "ovsdb-data.h"
 #include "ovsdb-error.h"
 #include "ovsdb-parser.h"
@@ -211,7 +211,7 @@ ovsdb_execute_abort(struct ovsdb_execution *x UNUSED,
 static struct ovsdb_error *
 do_commit(struct ovsdb_execution *x)
 {
-    if (x->db->file) {
+    if (x->db->log) {
         struct ovsdb_error *error;
         struct json *json;
 
@@ -221,14 +221,14 @@ do_commit(struct ovsdb_execution *x)
             return NULL;
         }
 
-        error = ovsdb_file_write(x->db->file, json);
+        error = ovsdb_log_write(x->db->log, json);
         json_destroy(json);
         if (error) {
             return ovsdb_wrap_error(error, "writing transaction failed");
         }
 
         if (x->durable) {
-            error = ovsdb_file_commit(x->db->file);
+            error = ovsdb_log_commit(x->db->log);
             if (error) {
                 return ovsdb_wrap_error(error,
                                         "committing transaction failed");
diff --git a/ovsdb/file.c b/ovsdb/file.c
deleted file mode 100644 (file)
index 4883d76..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-/* Copyright (c) 2009 Nicira Networks
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <config.h>
-
-#include "file.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "json.h"
-#include "lockfile.h"
-#include "ovsdb-error.h"
-#include "sha1.h"
-#include "util.h"
-
-#define THIS_MODULE VLM_ovsdb_file
-#include "vlog.h"
-
-enum ovsdb_file_mode {
-    OVSDB_FILE_READ,
-    OVSDB_FILE_WRITE
-};
-
-struct ovsdb_file {
-    off_t offset;
-    char *name;
-    struct lockfile *lockfile;
-    FILE *stream;
-    struct ovsdb_error *read_error;
-    struct ovsdb_error *write_error;
-    enum ovsdb_file_mode mode;
-};
-
-struct ovsdb_error *
-ovsdb_file_open(const char *name, int flags, struct ovsdb_file **filep)
-{
-    struct lockfile *lockfile;
-    struct ovsdb_error *error;
-    struct ovsdb_file *file;
-    struct stat s;
-    FILE *stream;
-    int accmode;
-    int fd;
-
-    *filep = NULL;
-
-    accmode = flags & O_ACCMODE;
-    if (accmode == O_RDWR || accmode == O_WRONLY) {
-        int retval = lockfile_lock(name, 0, &lockfile);
-        if (retval) {
-            error = ovsdb_io_error(retval, "%s: failed to lock lockfile",
-                                   name);
-            goto error;
-        }
-    } else {
-        lockfile = NULL;
-    }
-
-    fd = open(name, flags, 0666);
-    if (fd < 0) {
-        const char *op = flags & O_CREAT && flags & O_EXCL ? "create" : "open";
-        error = ovsdb_io_error(errno, "%s: %s failed", op, name);
-        goto error_unlock;
-    }
-
-    if (!fstat(fd, &s) && s.st_size == 0) {
-        /* It's (probably) a new file so fsync() its parent directory to ensure
-         * that its directory entry is committed to disk. */
-        char *dir = dir_name(name);
-        int dirfd = open(dir, O_RDONLY);
-        if (dirfd >= 0) {
-            if (fsync(dirfd) && errno != EINVAL) {
-                VLOG_ERR("%s: fsync failed (%s)", dir, strerror(errno));
-            }
-            close(dirfd);
-        } else {
-            VLOG_ERR("%s: open failed (%s)", dir, strerror(errno));
-        }
-        free(dir);
-    }
-
-    stream = fdopen(fd, (accmode == O_RDONLY ? "rb"
-                         : accmode == O_WRONLY ? "wb"
-                         : "w+b"));
-    if (!stream) {
-        error = ovsdb_io_error(errno, "%s: fdopen failed", name);
-        goto error_close;
-    }
-
-    file = xmalloc(sizeof *file);
-    file->name = xstrdup(name);
-    file->lockfile = lockfile;
-    file->stream = stream;
-    file->offset = 0;
-    file->read_error = NULL;
-    file->write_error = NULL;
-    file->mode = OVSDB_FILE_READ;
-    *filep = file;
-    return NULL;
-
-error_close:
-    close(fd);
-error_unlock:
-    lockfile_unlock(lockfile);
-error:
-    return error;
-}
-
-void
-ovsdb_file_close(struct ovsdb_file *file)
-{
-    if (file) {
-        free(file->name);
-        fclose(file->stream);
-        lockfile_unlock(file->lockfile);
-        ovsdb_error_destroy(file->read_error);
-        ovsdb_error_destroy(file->write_error);
-        free(file);
-    }
-}
-
-static const char magic[] = "OVSDB JSON ";
-
-static bool
-parse_header(char *header, unsigned long int *length,
-             uint8_t sha1[SHA1_DIGEST_SIZE])
-{
-    char *p;
-
-    /* 'header' must consist of a magic string... */
-    if (strncmp(header, magic, strlen(magic))) {
-        return false;
-    }
-
-    /* ...followed by a length in bytes... */
-    *length = strtoul(header + strlen(magic), &p, 10);
-    if (!*length || *length == ULONG_MAX || *p != ' ') {
-        return false;
-    }
-    p++;
-
-    /* ...followed by a SHA-1 hash... */
-    if (!sha1_from_hex(sha1, p)) {
-        return false;
-    }
-    p += SHA1_HEX_DIGEST_LEN;
-
-    /* ...and ended by a new-line. */
-    if (*p != '\n') {
-        return false;
-    }
-
-    return true;
-}
-
-struct ovsdb_file_read_cbdata {
-    char input[4096];
-    struct ovsdb_file *file;
-    int error;
-    unsigned long length;
-};
-
-static struct ovsdb_error *
-parse_body(struct ovsdb_file *file, off_t offset, unsigned long int length,
-           uint8_t sha1[SHA1_DIGEST_SIZE], struct json **jsonp)
-{
-    unsigned long int bytes_left;
-    struct json_parser *parser;
-    struct sha1_ctx ctx;
-
-    sha1_init(&ctx);
-    parser = json_parser_create(JSPF_TRAILER);
-
-    bytes_left = length;
-    while (length > 0) {
-        char input[BUFSIZ];
-        int chunk;
-
-        chunk = MIN(length, sizeof input);
-        if (fread(input, 1, chunk, file->stream) != chunk) {
-            json_parser_abort(parser);
-            return ovsdb_io_error(ferror(file->stream) ? errno : EOF,
-                                  "%s: error reading %lu bytes "
-                                  "starting at offset %lld", file->name,
-                                  length, (long long int) offset);
-        }
-        sha1_update(&ctx, input, chunk);
-        json_parser_feed(parser, input, chunk);
-        length -= chunk;
-    }
-
-    sha1_final(&ctx, sha1);
-    *jsonp = json_parser_finish(parser);
-    return NULL;
-}
-
-struct ovsdb_error *
-ovsdb_file_read(struct ovsdb_file *file, struct json **jsonp)
-{
-    uint8_t expected_sha1[SHA1_DIGEST_SIZE];
-    uint8_t actual_sha1[SHA1_DIGEST_SIZE];
-    struct ovsdb_error *error;
-    off_t data_offset;
-    unsigned long data_length;
-    struct json *json;
-    char header[128];
-
-    *jsonp = json = NULL;
-
-    if (file->read_error) {
-        return ovsdb_error_clone(file->read_error);
-    } else if (file->mode == OVSDB_FILE_WRITE) {
-        return OVSDB_BUG("reading file in write mode");
-    }
-
-    if (!fgets(header, sizeof header, file->stream)) {
-        if (feof(file->stream)) {
-            error = NULL;
-        } else {
-            error = ovsdb_io_error(errno, "%s: read failed", file->name);
-        }
-        goto error;
-    }
-
-    if (!parse_header(header, &data_length, expected_sha1)) {
-        error = ovsdb_syntax_error(NULL, NULL, "%s: parse error at offset "
-                                   "%lld in header line \"%.*s\"",
-                                   file->name, (long long int) file->offset,
-                                   (int) strcspn(header, "\n"), header);
-        goto error;
-    }
-
-    data_offset = file->offset + strlen(header);
-    error = parse_body(file, data_offset, data_length, actual_sha1, &json);
-    if (error) {
-        goto error;
-    }
-
-    if (memcmp(expected_sha1, actual_sha1, SHA1_DIGEST_SIZE)) {
-        error = ovsdb_syntax_error(NULL, NULL, "%s: %lu bytes starting at "
-                                   "offset %lld have SHA-1 hash "SHA1_FMT" "
-                                   "but should have hash "SHA1_FMT,
-                                   file->name, data_length,
-                                   (long long int) data_offset,
-                                   SHA1_ARGS(actual_sha1),
-                                   SHA1_ARGS(expected_sha1));
-        goto error;
-    }
-
-    if (json->type == JSON_STRING) {
-        error = ovsdb_syntax_error(NULL, NULL, "%s: %lu bytes starting at "
-                                   "offset %lld are not valid JSON (%s)",
-                                   file->name, data_length,
-                                   (long long int) data_offset,
-                                   json->u.string);
-        goto error;
-    }
-
-    file->offset = data_offset + data_length;
-    *jsonp = json;
-    return 0;
-
-error:
-    file->read_error = ovsdb_error_clone(error);
-    json_destroy(json);
-    return error;
-}
-
-struct ovsdb_error *
-ovsdb_file_write(struct ovsdb_file *file, struct json *json)
-{
-    uint8_t sha1[SHA1_DIGEST_SIZE];
-    struct ovsdb_error *error;
-    char *json_string;
-    char header[128];
-    size_t length;
-
-    json_string = NULL;
-
-    if (file->write_error) {
-        return ovsdb_error_clone(file->write_error);
-    } else if (file->mode == OVSDB_FILE_READ) {
-        file->mode = OVSDB_FILE_WRITE;
-        if (fseeko(file->stream, file->offset, SEEK_SET)) {
-            error = ovsdb_io_error(errno, "%s: cannot seek to offset %lld",
-                                   file->name, (long long int) file->offset);
-            goto error;
-        }
-        if (ftruncate(fileno(file->stream), file->offset)) {
-            error = ovsdb_io_error(errno, "%s: cannot truncate to length %lld",
-                                   file->name, (long long int) file->offset);
-            goto error;
-        }
-    }
-
-    if (json->type != JSON_OBJECT && json->type != JSON_ARRAY) {
-        error = OVSDB_BUG("bad JSON type");
-        goto error;
-    }
-
-    /* Compose content.  Add a new-line (replacing the null terminator) to make
-     * the file easier to read, even though it has no semantic value.  */
-    json_string = json_to_string(json, 0);
-    length = strlen(json_string) + 1;
-    json_string[length - 1] = '\n';
-
-    /* Compose header. */
-    sha1_bytes(json_string, length, sha1);
-    snprintf(header, sizeof header, "%s%zu "SHA1_FMT"\n",
-             magic, length, SHA1_ARGS(sha1));
-
-    /* Write. */
-    if (fwrite(header, strlen(header), 1, file->stream) != 1
-        || fwrite(json_string, length, 1, file->stream) != 1
-        || fflush(file->stream))
-    {
-        error = ovsdb_io_error(errno, "%s: write failed", file->name);
-
-        /* Remove any partially written data, ignoring errors since there is
-         * nothing further we can do. */
-        ftruncate(fileno(file->stream), file->offset);
-
-        goto error;
-    }
-
-    file->offset += strlen(header) + length;
-    free(json_string);
-    return 0;
-
-error:
-    file->write_error = ovsdb_error_clone(error);
-    free(json_string);
-    return error;
-}
-
-struct ovsdb_error *
-ovsdb_file_commit(struct ovsdb_file *file)
-{
-    if (fsync(fileno(file->stream))) {
-        return ovsdb_io_error(errno, "%s: fsync failed", file->name);
-    }
-    return 0;
-}
diff --git a/ovsdb/file.h b/ovsdb/file.h
deleted file mode 100644 (file)
index 5178140..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (c) 2009 Nicira Networks
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef OVSDB_FILE_H
-#define OVSDB_FILE_H 1
-
-#include <sys/types.h>
-#include "compiler.h"
-
-struct json;
-struct ovsdb_file;
-
-struct ovsdb_error *ovsdb_file_open(const char *name, int flags,
-                                    struct ovsdb_file **) WARN_UNUSED_RESULT;
-void ovsdb_file_close(struct ovsdb_file *);
-
-struct ovsdb_error *ovsdb_file_read(struct ovsdb_file *, struct json **)
-    WARN_UNUSED_RESULT;
-struct ovsdb_error *ovsdb_file_write(struct ovsdb_file *, struct json *)
-    WARN_UNUSED_RESULT;
-struct ovsdb_error *ovsdb_file_commit(struct ovsdb_file *)
-    WARN_UNUSED_RESULT;
-
-#endif /* ovsdb/file.h */
diff --git a/ovsdb/log.c b/ovsdb/log.c
new file mode 100644 (file)
index 0000000..9c2e277
--- /dev/null
@@ -0,0 +1,363 @@
+/* Copyright (c) 2009 Nicira Networks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "log.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "json.h"
+#include "lockfile.h"
+#include "ovsdb.h"
+#include "ovsdb-error.h"
+#include "sha1.h"
+#include "transaction.h"
+#include "util.h"
+
+#define THIS_MODULE VLM_ovsdb_log
+#include "vlog.h"
+
+enum ovsdb_log_mode {
+    OVSDB_LOG_READ,
+    OVSDB_LOG_WRITE
+};
+
+struct ovsdb_log {
+    off_t offset;
+    char *name;
+    struct lockfile *lockfile;
+    FILE *stream;
+    struct ovsdb_error *read_error;
+    struct ovsdb_error *write_error;
+    enum ovsdb_log_mode mode;
+};
+
+struct ovsdb_error *
+ovsdb_log_open(const char *name, int flags, struct ovsdb_log **filep)
+{
+    struct lockfile *lockfile;
+    struct ovsdb_error *error;
+    struct ovsdb_log *file;
+    struct stat s;
+    FILE *stream;
+    int accmode;
+    int fd;
+
+    *filep = NULL;
+
+    accmode = flags & O_ACCMODE;
+    if (accmode == O_RDWR || accmode == O_WRONLY) {
+        int retval = lockfile_lock(name, 0, &lockfile);
+        if (retval) {
+            error = ovsdb_io_error(retval, "%s: failed to lock lockfile",
+                                   name);
+            goto error;
+        }
+    } else {
+        lockfile = NULL;
+    }
+
+    fd = open(name, flags, 0666);
+    if (fd < 0) {
+        const char *op = flags & O_CREAT && flags & O_EXCL ? "create" : "open";
+        error = ovsdb_io_error(errno, "%s: %s failed", op, name);
+        goto error_unlock;
+    }
+
+    if (!fstat(fd, &s) && s.st_size == 0) {
+        /* It's (probably) a new file so fsync() its parent directory to ensure
+         * that its directory entry is committed to disk. */
+        char *dir = dir_name(name);
+        int dirfd = open(dir, O_RDONLY);
+        if (dirfd >= 0) {
+            if (fsync(dirfd) && errno != EINVAL) {
+                VLOG_ERR("%s: fsync failed (%s)", dir, strerror(errno));
+            }
+            close(dirfd);
+        } else {
+            VLOG_ERR("%s: open failed (%s)", dir, strerror(errno));
+        }
+        free(dir);
+    }
+
+    stream = fdopen(fd, (accmode == O_RDONLY ? "rb"
+                         : accmode == O_WRONLY ? "wb"
+                         : "w+b"));
+    if (!stream) {
+        error = ovsdb_io_error(errno, "%s: fdopen failed", name);
+        goto error_close;
+    }
+
+    file = xmalloc(sizeof *file);
+    file->name = xstrdup(name);
+    file->lockfile = lockfile;
+    file->stream = stream;
+    file->offset = 0;
+    file->read_error = NULL;
+    file->write_error = NULL;
+    file->mode = OVSDB_LOG_READ;
+    *filep = file;
+    return NULL;
+
+error_close:
+    close(fd);
+error_unlock:
+    lockfile_unlock(lockfile);
+error:
+    return error;
+}
+
+void
+ovsdb_log_close(struct ovsdb_log *file)
+{
+    if (file) {
+        free(file->name);
+        fclose(file->stream);
+        lockfile_unlock(file->lockfile);
+        ovsdb_error_destroy(file->read_error);
+        ovsdb_error_destroy(file->write_error);
+        free(file);
+    }
+}
+
+static const char magic[] = "OVSDB JSON ";
+
+static bool
+parse_header(char *header, unsigned long int *length,
+             uint8_t sha1[SHA1_DIGEST_SIZE])
+{
+    char *p;
+
+    /* 'header' must consist of a magic string... */
+    if (strncmp(header, magic, strlen(magic))) {
+        return false;
+    }
+
+    /* ...followed by a length in bytes... */
+    *length = strtoul(header + strlen(magic), &p, 10);
+    if (!*length || *length == ULONG_MAX || *p != ' ') {
+        return false;
+    }
+    p++;
+
+    /* ...followed by a SHA-1 hash... */
+    if (!sha1_from_hex(sha1, p)) {
+        return false;
+    }
+    p += SHA1_HEX_DIGEST_LEN;
+
+    /* ...and ended by a new-line. */
+    if (*p != '\n') {
+        return false;
+    }
+
+    return true;
+}
+
+struct ovsdb_log_read_cbdata {
+    char input[4096];
+    struct ovsdb_log *file;
+    int error;
+    unsigned long length;
+};
+
+static struct ovsdb_error *
+parse_body(struct ovsdb_log *file, off_t offset, unsigned long int length,
+           uint8_t sha1[SHA1_DIGEST_SIZE], struct json **jsonp)
+{
+    unsigned long int bytes_left;
+    struct json_parser *parser;
+    struct sha1_ctx ctx;
+
+    sha1_init(&ctx);
+    parser = json_parser_create(JSPF_TRAILER);
+
+    bytes_left = length;
+    while (length > 0) {
+        char input[BUFSIZ];
+        int chunk;
+
+        chunk = MIN(length, sizeof input);
+        if (fread(input, 1, chunk, file->stream) != chunk) {
+            json_parser_abort(parser);
+            return ovsdb_io_error(ferror(file->stream) ? errno : EOF,
+                                  "%s: error reading %lu bytes "
+                                  "starting at offset %lld", file->name,
+                                  length, (long long int) offset);
+        }
+        sha1_update(&ctx, input, chunk);
+        json_parser_feed(parser, input, chunk);
+        length -= chunk;
+    }
+
+    sha1_final(&ctx, sha1);
+    *jsonp = json_parser_finish(parser);
+    return NULL;
+}
+
+struct ovsdb_error *
+ovsdb_log_read(struct ovsdb_log *file, struct json **jsonp)
+{
+    uint8_t expected_sha1[SHA1_DIGEST_SIZE];
+    uint8_t actual_sha1[SHA1_DIGEST_SIZE];
+    struct ovsdb_error *error;
+    off_t data_offset;
+    unsigned long data_length;
+    struct json *json;
+    char header[128];
+
+    *jsonp = json = NULL;
+
+    if (file->read_error) {
+        return ovsdb_error_clone(file->read_error);
+    } else if (file->mode == OVSDB_LOG_WRITE) {
+        return OVSDB_BUG("reading file in write mode");
+    }
+
+    if (!fgets(header, sizeof header, file->stream)) {
+        if (feof(file->stream)) {
+            error = NULL;
+        } else {
+            error = ovsdb_io_error(errno, "%s: read failed", file->name);
+        }
+        goto error;
+    }
+
+    if (!parse_header(header, &data_length, expected_sha1)) {
+        error = ovsdb_syntax_error(NULL, NULL, "%s: parse error at offset "
+                                   "%lld in header line \"%.*s\"",
+                                   file->name, (long long int) file->offset,
+                                   (int) strcspn(header, "\n"), header);
+        goto error;
+    }
+
+    data_offset = file->offset + strlen(header);
+    error = parse_body(file, data_offset, data_length, actual_sha1, &json);
+    if (error) {
+        goto error;
+    }
+
+    if (memcmp(expected_sha1, actual_sha1, SHA1_DIGEST_SIZE)) {
+        error = ovsdb_syntax_error(NULL, NULL, "%s: %lu bytes starting at "
+                                   "offset %lld have SHA-1 hash "SHA1_FMT" "
+                                   "but should have hash "SHA1_FMT,
+                                   file->name, data_length,
+                                   (long long int) data_offset,
+                                   SHA1_ARGS(actual_sha1),
+                                   SHA1_ARGS(expected_sha1));
+        goto error;
+    }
+
+    if (json->type == JSON_STRING) {
+        error = ovsdb_syntax_error(NULL, NULL, "%s: %lu bytes starting at "
+                                   "offset %lld are not valid JSON (%s)",
+                                   file->name, data_length,
+                                   (long long int) data_offset,
+                                   json->u.string);
+        goto error;
+    }
+
+    file->offset = data_offset + data_length;
+    *jsonp = json;
+    return 0;
+
+error:
+    file->read_error = ovsdb_error_clone(error);
+    json_destroy(json);
+    return error;
+}
+
+struct ovsdb_error *
+ovsdb_log_write(struct ovsdb_log *file, struct json *json)
+{
+    uint8_t sha1[SHA1_DIGEST_SIZE];
+    struct ovsdb_error *error;
+    char *json_string;
+    char header[128];
+    size_t length;
+
+    json_string = NULL;
+
+    if (file->write_error) {
+        return ovsdb_error_clone(file->write_error);
+    } else if (file->mode == OVSDB_LOG_READ) {
+        file->mode = OVSDB_LOG_WRITE;
+        if (fseeko(file->stream, file->offset, SEEK_SET)) {
+            error = ovsdb_io_error(errno, "%s: cannot seek to offset %lld",
+                                   file->name, (long long int) file->offset);
+            goto error;
+        }
+        if (ftruncate(fileno(file->stream), file->offset)) {
+            error = ovsdb_io_error(errno, "%s: cannot truncate to length %lld",
+                                   file->name, (long long int) file->offset);
+            goto error;
+        }
+    }
+
+    if (json->type != JSON_OBJECT && json->type != JSON_ARRAY) {
+        error = OVSDB_BUG("bad JSON type");
+        goto error;
+    }
+
+    /* Compose content.  Add a new-line (replacing the null terminator) to make
+     * the file easier to read, even though it has no semantic value.  */
+    json_string = json_to_string(json, 0);
+    length = strlen(json_string) + 1;
+    json_string[length - 1] = '\n';
+
+    /* Compose header. */
+    sha1_bytes(json_string, length, sha1);
+    snprintf(header, sizeof header, "%s%zu "SHA1_FMT"\n",
+             magic, length, SHA1_ARGS(sha1));
+
+    /* Write. */
+    if (fwrite(header, strlen(header), 1, file->stream) != 1
+        || fwrite(json_string, length, 1, file->stream) != 1
+        || fflush(file->stream))
+    {
+        error = ovsdb_io_error(errno, "%s: write failed", file->name);
+
+        /* Remove any partially written data, ignoring errors since there is
+         * nothing further we can do. */
+        ftruncate(fileno(file->stream), file->offset);
+
+        goto error;
+    }
+
+    file->offset += strlen(header) + length;
+    free(json_string);
+    return 0;
+
+error:
+    file->write_error = ovsdb_error_clone(error);
+    free(json_string);
+    return error;
+}
+
+struct ovsdb_error *
+ovsdb_log_commit(struct ovsdb_log *file)
+{
+    if (fsync(fileno(file->stream))) {
+        return ovsdb_io_error(errno, "%s: fsync failed", file->name);
+    }
+    return 0;
+}
+
diff --git a/ovsdb/log.h b/ovsdb/log.h
new file mode 100644 (file)
index 0000000..2daa635
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (c) 2009 Nicira Networks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVSDB_LOG_H
+#define OVSDB_LOG_H 1
+
+#include <sys/types.h>
+#include "compiler.h"
+
+struct json;
+struct ovsdb_log;
+
+struct ovsdb_error *ovsdb_log_open(const char *name, int flags,
+                                   struct ovsdb_log **) WARN_UNUSED_RESULT;
+void ovsdb_log_close(struct ovsdb_log *);
+
+struct ovsdb_error *ovsdb_log_read(struct ovsdb_log *, struct json **)
+    WARN_UNUSED_RESULT;
+struct ovsdb_error *ovsdb_log_write(struct ovsdb_log *, struct json *)
+    WARN_UNUSED_RESULT;
+struct ovsdb_error *ovsdb_log_commit(struct ovsdb_log *)
+    WARN_UNUSED_RESULT;
+
+#endif /* ovsdb/log.h */
index d6e0ff9..8b81ef6 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "command-line.h"
 #include "compiler.h"
-#include "file.h"
+#include "log.h"
 #include "json.h"
 #include "ovsdb.h"
 #include "ovsdb-error.h"
@@ -144,7 +144,7 @@ do_create(int argc UNUSED, char *argv[])
     const char *db_file_name = argv[1];
     const char *schema_file_name = argv[2];
     struct ovsdb_schema *schema;
-    struct ovsdb_file *db_file;
+    struct ovsdb_log *log;
     struct json *json;
 
     /* Read schema from file and convert to JSON. */
@@ -152,11 +152,11 @@ do_create(int argc UNUSED, char *argv[])
     json = ovsdb_schema_to_json(schema);
 
     /* Create database file. */
-    check_ovsdb_error(ovsdb_file_open(db_file_name, O_RDWR | O_CREAT | O_EXCL,
-                                      &db_file));
-    check_ovsdb_error(ovsdb_file_write(db_file, json));
-    check_ovsdb_error(ovsdb_file_commit(db_file));
-    ovsdb_file_close(db_file);
+    check_ovsdb_error(ovsdb_log_open(db_file_name, O_RDWR | O_CREAT | O_EXCL,
+                                     &log));
+    check_ovsdb_error(ovsdb_log_write(log, json));
+    check_ovsdb_error(ovsdb_log_commit(log));
+    ovsdb_log_close(log);
 
     json_destroy(json);
 }
index 6d0f131..7caa229 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <fcntl.h>
 
-#include "file.h"
+#include "log.h"
 #include "json.h"
 #include "ovsdb-error.h"
 #include "ovsdb-parser.h"
@@ -153,14 +153,14 @@ ovsdb_schema_to_json(const struct ovsdb_schema *schema)
 }
 \f
 struct ovsdb *
-ovsdb_create(struct ovsdb_file *file, struct ovsdb_schema *schema)
+ovsdb_create(struct ovsdb_log *log, struct ovsdb_schema *schema)
 {
     struct shash_node *node;
     struct ovsdb *db;
 
     db = xmalloc(sizeof *db);
     db->schema = schema;
-    db->file = file;
+    db->log = log;
     list_init(&db->triggers);
     db->run_triggers = false;
 
@@ -178,16 +178,16 @@ ovsdb_open(const char *file_name, bool read_only, struct ovsdb **dbp)
 {
     struct ovsdb_schema *schema;
     struct ovsdb_error *error;
-    struct ovsdb_file *file;
+    struct ovsdb_log *log;
     struct json *json;
     struct ovsdb *db;
 
-    error = ovsdb_file_open(file_name, read_only ? O_RDONLY : O_RDWR, &file);
+    error = ovsdb_log_open(file_name, read_only ? O_RDONLY : O_RDWR, &log);
     if (error) {
         return error;
     }
 
-    error = ovsdb_file_read(file, &json);
+    error = ovsdb_log_read(log, &json);
     if (error) {
         return error;
     } else if (!json) {
@@ -204,8 +204,8 @@ ovsdb_open(const char *file_name, bool read_only, struct ovsdb **dbp)
     }
     json_destroy(json);
 
-    db = ovsdb_create(read_only ? NULL : file, schema);
-    while ((error = ovsdb_file_read(file, &json)) == NULL && json) {
+    db = ovsdb_create(read_only ? NULL : log, schema);
+    while ((error = ovsdb_log_read(log, &json)) == NULL && json) {
         struct ovsdb_txn *txn;
 
         error = ovsdb_txn_from_json(db, json, &txn);
@@ -225,7 +225,7 @@ ovsdb_open(const char *file_name, bool read_only, struct ovsdb **dbp)
     }
 
     if (read_only) {
-        ovsdb_file_close(file);
+        ovsdb_log_close(log);
     }
 
     *dbp = db;
@@ -251,7 +251,7 @@ ovsdb_destroy(struct ovsdb *db)
         shash_clear(&db->schema->tables);
 
         ovsdb_schema_destroy(db->schema);
-        ovsdb_file_close(db->file);
+        ovsdb_log_close(db->log);
         free(db);
     }
 }
index 3f62966..d57ebfc 100644 (file)
@@ -46,7 +46,7 @@ struct json *ovsdb_schema_to_json(const struct ovsdb_schema *);
 /* Database. */
 struct ovsdb {
     struct ovsdb_schema *schema;
-    struct ovsdb_file *file;    /* Disk file (null for in-memory db). */
+    struct ovsdb_log *log;      /* Disk log (null for in-memory db). */
     struct shash tables;        /* Contains "struct ovsdb_table *"s. */
 
     /* Triggers. */
@@ -54,7 +54,7 @@ struct ovsdb {
     bool run_triggers;
 };
 
-struct ovsdb *ovsdb_create(struct ovsdb_file *, struct ovsdb_schema *);
+struct ovsdb *ovsdb_create(struct ovsdb_log *, struct ovsdb_schema *);
 struct ovsdb_error *ovsdb_open(const char *file_name, bool read_only,
                                struct ovsdb **)
     WARN_UNUSED_RESULT;
index f662d95..3a54e13 100644 (file)
@@ -17,7 +17,7 @@ TESTSUITE_AT = \
        tests/lockfile.at \
        tests/reconnect.at \
        tests/ovsdb.at \
-       tests/ovsdb-file.at \
+       tests/ovsdb-log.at \
        tests/ovsdb-types.at \
        tests/ovsdb-data.at \
        tests/ovsdb-column.at \
diff --git a/tests/ovsdb-file.at b/tests/ovsdb-file.at
deleted file mode 100644 (file)
index c85b29e..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-AT_BANNER([OVSDB -- file I/O])
-
-AT_SETUP([create empty, reread])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_CREAT|O_RDWR'], [0], 
-  [file: open successful
-], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read], [0], 
-  [file: open successful
-file: read: end of file
-], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([write one, reread])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[0]']], [0], 
-  [[file: open successful
-file: write:[0] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read read], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: end of file
-]], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([check that O_EXCL works])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[1]']], [0], 
-  [[file: open successful
-file: write:[1] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read], [0], 
-  [[file: open successful
-file: read: [1]
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_CREAT|O_RDWR|O_EXCL' read], [1], 
-  [], [test-ovsdb: I/O error: create: file failed (File exists)
-])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([write one, reread])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
-  [[file: open successful
-file: write:[0] successful
-file: write:[1] successful
-file: write:[2] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read read read read], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: [2]
-file: read: end of file
-]], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([write one, reread, append])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
-  [[file: open successful
-file: write:[0] successful
-file: write:[1] successful
-file: write:[2] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_RDWR' read read read 'write:["append"]']], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: [2]
-file: write:["append"] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read read read read read], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: [2]
-file: read: ["append"]
-file: read: end of file
-]], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([write, reread one, overwrite])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
-  [[file: open successful
-file: write:[0] successful
-file: write:[1] successful
-file: write:[2] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_RDWR' read 'write:["more data"]']], [0], 
-  [[file: open successful
-file: read: [0]
-file: write:["more data"] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read read read], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: ["more data"]
-file: read: end of file
-]], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([write, add corrupted data, read])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
-  [[file: open successful
-file: write:[0] successful
-file: write:[1] successful
-file: write:[2] successful
-]], [ignore])
-AT_CHECK([echo 'xxx' >> file])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read read read read], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: [2]
-file: read failed: syntax error: file: parse error at offset 174 in header line "xxx"
-]], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([write, add corrupted data, read, overwrite])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
-  [[file: open successful
-file: write:[0] successful
-file: write:[1] successful
-file: write:[2] successful
-]], [ignore])
-AT_CHECK([echo 'xxx' >> file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_RDWR' read read read read 'write:[3]']], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: [2]
-file: read failed: syntax error: file: parse error at offset 174 in header line "xxx"
-file: write:[3] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read read read read read], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: [2]
-file: read: [3]
-file: read: end of file
-]], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([write, corrupt some data, read, overwrite])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
-  [[file: open successful
-file: write:[0] successful
-file: write:[1] successful
-file: write:[2] successful
-]], [ignore])
-AT_CHECK([[sed 's/\[2]/[3]/' < file > file.tmp]])
-AT_CHECK([mv file.tmp file])
-AT_CHECK([[grep -c '\[3]' file]], [0], [1
-])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_RDWR' read read read 'write:["longer data"]']], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read failed: syntax error: file: 4 bytes starting at offset 170 have SHA-1 hash 5c031e5c0d3a9338cc127ebe40bb2748b6a67e78 but should have hash 98f55556e7ffd432381b56a19bd485b3e6446442
-file: write:["longer data"] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read read read read], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: ["longer data"]
-file: read: end of file
-]], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([write, truncate file, read, overwrite])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
-  [[file: open successful
-file: write:[0] successful
-file: write:[1] successful
-file: write:[2] successful
-]], [ignore])
-AT_CHECK([[sed 's/\[2]/2/' < file > file.tmp]])
-AT_CHECK([mv file.tmp file])
-AT_CHECK([[grep -c '^2$' file]], [0], [1
-])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_RDWR' read read read 'write:["longer data"]']], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read failed: I/O error: file: error reading 4 bytes starting at offset 170 (unexpected end of file)
-file: write:["longer data"] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read read read read], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: ["longer data"]
-file: read: end of file
-]], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
-
-AT_SETUP([write bad JSON, read, overwrite])
-AT_KEYWORDS([ovsdb file])
-AT_CAPTURE_FILE([file])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
-  [[file: open successful
-file: write:[0] successful
-file: write:[1] successful
-file: write:[2] successful
-]], [ignore])
-AT_CHECK([[printf '%s\n%s\n' 'OVSDB JSON 5 d910b02871075d3156ec8675dfc95b7d5d640aa6' 'null' >> file]])
-OVS_CHECK_LCOV(
-  [[test-ovsdb file-io file 'O_RDWR' read read read read 'write:["replacement data"]']], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: [2]
-file: read failed: syntax error: file: 5 bytes starting at offset 228 are not valid JSON (syntax error at beginning of input)
-file: write:["replacement data"] successful
-]], [ignore])
-OVS_CHECK_LCOV(
-  [test-ovsdb file-io file 'O_RDONLY' read read read read read], [0], 
-  [[file: open successful
-file: read: [0]
-file: read: [1]
-file: read: [2]
-file: read: ["replacement data"]
-file: read: end of file
-]], [ignore])
-AT_CHECK([test -f .file.~lock~])
-AT_CLEANUP
diff --git a/tests/ovsdb-log.at b/tests/ovsdb-log.at
new file mode 100644 (file)
index 0000000..b0c1c97
--- /dev/null
@@ -0,0 +1,282 @@
+AT_BANNER([OVSDB -- logging])
+
+AT_SETUP([create empty, reread])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([log])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_CREAT|O_RDWR'], [0], 
+  [file: open successful
+], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read], [0], 
+  [file: open successful
+file: read: end of log
+], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([write one, reread])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[0]']], [0], 
+  [[file: open successful
+file: write:[0] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read read], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: end of log
+]], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([check that O_EXCL works])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[1]']], [0], 
+  [[file: open successful
+file: write:[1] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read], [0], 
+  [[file: open successful
+file: read: [1]
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_CREAT|O_RDWR|O_EXCL' read], [1], 
+  [], [test-ovsdb: I/O error: create: file failed (File exists)
+])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([write one, reread])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
+  [[file: open successful
+file: write:[0] successful
+file: write:[1] successful
+file: write:[2] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read read read read], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: [2]
+file: read: end of log
+]], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([write one, reread, append])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
+  [[file: open successful
+file: write:[0] successful
+file: write:[1] successful
+file: write:[2] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_RDWR' read read read 'write:["append"]']], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: [2]
+file: write:["append"] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read read read read read], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: [2]
+file: read: ["append"]
+file: read: end of log
+]], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([write, reread one, overwrite])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
+  [[file: open successful
+file: write:[0] successful
+file: write:[1] successful
+file: write:[2] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_RDWR' read 'write:["more data"]']], [0], 
+  [[file: open successful
+file: read: [0]
+file: write:["more data"] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read read read], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: ["more data"]
+file: read: end of log
+]], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([write, add corrupted data, read])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
+  [[file: open successful
+file: write:[0] successful
+file: write:[1] successful
+file: write:[2] successful
+]], [ignore])
+AT_CHECK([echo 'xxx' >> file])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read read read read], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: [2]
+file: read failed: syntax error: file: parse error at offset 174 in header line "xxx"
+]], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([write, add corrupted data, read, overwrite])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
+  [[file: open successful
+file: write:[0] successful
+file: write:[1] successful
+file: write:[2] successful
+]], [ignore])
+AT_CHECK([echo 'xxx' >> file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_RDWR' read read read read 'write:[3]']], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: [2]
+file: read failed: syntax error: file: parse error at offset 174 in header line "xxx"
+file: write:[3] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read read read read read], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: [2]
+file: read: [3]
+file: read: end of log
+]], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([write, corrupt some data, read, overwrite])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
+  [[file: open successful
+file: write:[0] successful
+file: write:[1] successful
+file: write:[2] successful
+]], [ignore])
+AT_CHECK([[sed 's/\[2]/[3]/' < file > file.tmp]])
+AT_CHECK([mv file.tmp file])
+AT_CHECK([[grep -c '\[3]' file]], [0], [1
+])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_RDWR' read read read 'write:["longer data"]']], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read failed: syntax error: file: 4 bytes starting at offset 170 have SHA-1 hash 5c031e5c0d3a9338cc127ebe40bb2748b6a67e78 but should have hash 98f55556e7ffd432381b56a19bd485b3e6446442
+file: write:["longer data"] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read read read read], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: ["longer data"]
+file: read: end of log
+]], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([write, truncate file, read, overwrite])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
+  [[file: open successful
+file: write:[0] successful
+file: write:[1] successful
+file: write:[2] successful
+]], [ignore])
+AT_CHECK([[sed 's/\[2]/2/' < file > file.tmp]])
+AT_CHECK([mv file.tmp file])
+AT_CHECK([[grep -c '^2$' file]], [0], [1
+])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_RDWR' read read read 'write:["longer data"]']], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read failed: I/O error: file: error reading 4 bytes starting at offset 170 (unexpected end of file)
+file: write:["longer data"] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read read read read], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: ["longer data"]
+file: read: end of log
+]], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
+
+AT_SETUP([write bad JSON, read, overwrite])
+AT_KEYWORDS([ovsdb log])
+AT_CAPTURE_FILE([file])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_CREAT|O_RDWR' 'write:[0]' 'write:[1]' 'write:[2]']], [0], 
+  [[file: open successful
+file: write:[0] successful
+file: write:[1] successful
+file: write:[2] successful
+]], [ignore])
+AT_CHECK([[printf '%s\n%s\n' 'OVSDB JSON 5 d910b02871075d3156ec8675dfc95b7d5d640aa6' 'null' >> file]])
+OVS_CHECK_LCOV(
+  [[test-ovsdb log-io file 'O_RDWR' read read read read 'write:["replacement data"]']], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: [2]
+file: read failed: syntax error: file: 5 bytes starting at offset 228 are not valid JSON (syntax error at beginning of input)
+file: write:["replacement data"] successful
+]], [ignore])
+OVS_CHECK_LCOV(
+  [test-ovsdb log-io file 'O_RDONLY' read read read read read], [0], 
+  [[file: open successful
+file: read: [0]
+file: read: [1]
+file: read: [2]
+file: read: ["replacement data"]
+file: read: end of log
+]], [ignore])
+AT_CHECK([test -f .file.~lock~])
+AT_CLEANUP
index 0e0e63b..d3d53bc 100644 (file)
@@ -22,7 +22,7 @@ m4_define([OVSDB_CHECK_NEGATIVE],
             [0], [ignore], [ignore])
    AT_CLEANUP])
 
-m4_include([tests/ovsdb-file.at])
+m4_include([tests/ovsdb-log.at])
 m4_include([tests/ovsdb-types.at])
 m4_include([tests/ovsdb-data.at])
 m4_include([tests/ovsdb-column.at])
index bee1818..72fada1 100644 (file)
@@ -30,7 +30,7 @@
 #include "ovsdb-types.h"
 #include "ovsdb/column.h"
 #include "ovsdb/condition.h"
-#include "ovsdb/file.h"
+#include "ovsdb/log.h"
 #include "ovsdb/ovsdb.h"
 #include "ovsdb/query.h"
 #include "ovsdb/row.h"
@@ -98,7 +98,7 @@ usage(void)
 {
     printf("%s: Open vSwitch database test utility\n"
            "usage: %s [OPTIONS] COMMAND [ARG...]\n\n"
-           "  file-io FILE FLAGS COMMAND...\n"
+           "  log-io FILE FLAGS COMMAND...\n"
            "    open FILE with FLAGS, run COMMANDs\n"
            "  parse-atomic-type TYPE\n"
            "    parse TYPE as OVSDB atomic type, and re-serialize\n"
@@ -196,13 +196,13 @@ check_ovsdb_error(struct ovsdb_error *error)
 /* Command implementations. */
 
 static void
-do_file_io(int argc, char *argv[])
+do_log_io(int argc, char *argv[])
 {
     const char *name = argv[1];
     char *mode = argv[2];
 
     struct ovsdb_error *error;
-    struct ovsdb_file *file;
+    struct ovsdb_log *log;
     char *save_ptr = NULL;
     const char *token;
     int flags;
@@ -226,7 +226,7 @@ do_file_io(int argc, char *argv[])
         }
     }
 
-    check_ovsdb_error(ovsdb_file_open(name, flags, &file));
+    check_ovsdb_error(ovsdb_log_open(name, flags, &log));
     printf("%s: open successful\n", name);
 
     for (i = 3; i < argc; i++) {
@@ -234,24 +234,24 @@ do_file_io(int argc, char *argv[])
         if (!strcmp(command, "read")) {
             struct json *json;
 
-            error = ovsdb_file_read(file, &json);
+            error = ovsdb_log_read(log, &json);
             if (!error) {
                 printf("%s: read: ", name);
                 if (json) {
                     print_and_free_json(json);
                 } else {
-                    printf("end of file\n");
+                    printf("end of log\n");
                 }
                 continue;
             }
         } else if (!strncmp(command, "write:", 6)) {
             struct json *json = parse_json(command + 6);
-            error = ovsdb_file_write(file, json);
+            error = ovsdb_log_write(log, json);
             json_destroy(json);
         } else if (!strcmp(command, "commit")) {
-            error = ovsdb_file_commit(file);
+            error = ovsdb_log_commit(log);
         } else {
-            ovs_fatal(0, "unknown file-io command \"%s\"", command);
+            ovs_fatal(0, "unknown log-io command \"%s\"", command);
         }
         if (error) {
             char *s = ovsdb_error_to_string(error);
@@ -262,7 +262,7 @@ do_file_io(int argc, char *argv[])
         }
     }
 
-    ovsdb_file_close(file);
+    ovsdb_log_close(log);
 }
 
 static void
@@ -1207,7 +1207,7 @@ do_transact(int argc, char *argv[])
 }
 
 static struct command all_commands[] = {
-    { "file-io", 2, INT_MAX, do_file_io },
+    { "log-io", 2, INT_MAX, do_log_io },
     { "parse-atomic-type", 1, 1, do_parse_atomic_type },
     { "parse-type", 1, 1, do_parse_type },
     { "parse-atoms", 2, INT_MAX, do_parse_atoms },