X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ovsdb%2Ffile.c;h=b02d5a3b2bf86696c498fc3b5b292cca2643a6cc;hb=2b13d312fc4d6e5eb1d0e3004fa523bb0c0ba544;hp=d09395c4cfc37207a3fbeeb842a7b79b95e9e0ff;hpb=d98e60075528c3065ad453f7add4b30f22edcde3;p=sliver-openvswitch.git diff --git a/ovsdb/file.c b/ovsdb/file.c index d09395c4c..b02d5a3b2 100644 --- a/ovsdb/file.c +++ b/ovsdb/file.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2010 Nicira Networks +/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ #include "file.h" -#include #include #include #include @@ -121,24 +120,16 @@ ovsdb_file_open_as_schema(const char *file_name, } static struct ovsdb_error * -ovsdb_file_open__(const char *file_name, - const struct ovsdb_schema *alternate_schema, - bool read_only, struct ovsdb **dbp, - struct ovsdb_file **filep) +ovsdb_file_open_log(const char *file_name, enum ovsdb_log_open_mode open_mode, + struct ovsdb_log **logp, struct ovsdb_schema **schemap) { - enum ovsdb_log_open_mode open_mode; - long long int oldest_commit; - unsigned int n_transactions; struct ovsdb_schema *schema = NULL; - struct ovsdb_error *error; struct ovsdb_log *log = NULL; - struct json *json; - struct ovsdb *db = NULL; + struct ovsdb_error *error; + struct json *json = NULL; - /* In read-only mode there is no ovsdb_file so 'filep' must be null. */ - assert(!(read_only && filep)); + ovs_assert(logp || schemap); - open_mode = read_only ? OVSDB_LOG_READ_ONLY : OVSDB_LOG_READ_WRITE; error = ovsdb_log_open(file_name, open_mode, -1, &log); if (error) { goto error; @@ -153,12 +144,9 @@ ovsdb_file_open__(const char *file_name, goto error; } - if (alternate_schema) { - schema = ovsdb_schema_clone(alternate_schema); - } else { + if (schemap) { error = ovsdb_schema_from_json(json, &schema); if (error) { - json_destroy(json); error = ovsdb_wrap_error(error, "failed to parse \"%s\" as ovsdb schema", file_name); @@ -167,8 +155,54 @@ ovsdb_file_open__(const char *file_name, } json_destroy(json); - db = ovsdb_create(schema); - schema = NULL; + if (logp) { + *logp = log; + } else { + ovsdb_log_close(log); + } + if (schemap) { + *schemap = schema; + } + return NULL; + +error: + ovsdb_log_close(log); + json_destroy(json); + if (logp) { + *logp = NULL; + } + if (schemap) { + *schemap = NULL; + } + return error; +} + +static struct ovsdb_error * +ovsdb_file_open__(const char *file_name, + const struct ovsdb_schema *alternate_schema, + bool read_only, struct ovsdb **dbp, + struct ovsdb_file **filep) +{ + enum ovsdb_log_open_mode open_mode; + long long int oldest_commit; + unsigned int n_transactions; + struct ovsdb_schema *schema = NULL; + struct ovsdb_error *error; + struct ovsdb_log *log; + struct json *json; + struct ovsdb *db = NULL; + + /* In read-only mode there is no ovsdb_file so 'filep' must be null. */ + ovs_assert(!(read_only && filep)); + + open_mode = read_only ? OVSDB_LOG_READ_ONLY : OVSDB_LOG_READ_WRITE; + error = ovsdb_file_open_log(file_name, open_mode, &log, + alternate_schema ? NULL : &schema); + if (error) { + goto error; + } + + db = ovsdb_create(schema ? schema : ovsdb_schema_clone(alternate_schema)); oldest_commit = LLONG_MAX; n_transactions = 0; @@ -180,6 +214,7 @@ ovsdb_file_open__(const char *file_name, &date, &txn); json_destroy(json); if (error) { + ovsdb_log_unread(log); break; } @@ -188,14 +223,18 @@ ovsdb_file_open__(const char *file_name, oldest_commit = date; } - ovsdb_txn_commit(txn, false); + error = ovsdb_txn_commit(txn, false); + if (error) { + ovsdb_log_unread(log); + break; + } } if (error) { /* Log error but otherwise ignore it. Probably the database just got * truncated due to power failure etc. and we should use its current * contents. */ char *msg = ovsdb_error_to_string(error); - VLOG_WARN("%s", msg); + VLOG_ERR("%s", msg); free(msg); ovsdb_error_destroy(error); @@ -225,7 +264,6 @@ error: *filep = NULL; } ovsdb_destroy(db); - ovsdb_schema_destroy(schema); ovsdb_log_close(log); return error; } @@ -294,10 +332,9 @@ ovsdb_file_txn_row_from_json(struct ovsdb_txn *txn, struct ovsdb_table *table, error = ovsdb_file_update_row_from_json(new, converting, json); if (error) { ovsdb_row_destroy(new); + } else { + ovsdb_txn_row_insert(txn, new); } - - ovsdb_txn_row_insert(txn, new); - return error; } } @@ -370,9 +407,7 @@ ovsdb_file_txn_from_json(struct ovsdb *db, const struct json *json, if (!table) { if (!strcmp(table_name, "_date") && node_json->type == JSON_INTEGER) { - if (date) { - *date = json_integer(node_json); - } + *date = json_integer(node_json); continue; } else if (!strcmp(table_name, "_comment") || converting) { continue; @@ -460,6 +495,17 @@ ovsdb_file_save_copy(const char *file_name, int locking, { return ovsdb_file_save_copy__(file_name, locking, comment, db, NULL); } + +/* Opens database 'file_name', reads its schema, and closes it. On success, + * stores the schema into '*schemap' and returns NULL; the caller then owns the + * schema. On failure, returns an ovsdb_error (which the caller must destroy) + * and sets '*dbp' to NULL. */ +struct ovsdb_error * +ovsdb_file_read_schema(const char *file_name, struct ovsdb_schema **schemap) +{ + ovs_assert(schemap != NULL); + return ovsdb_file_open_log(file_name, OVSDB_LOG_READ_ONLY, NULL, schemap); +} /* Replica implementation. */ @@ -484,11 +530,14 @@ ovsdb_file_create(struct ovsdb *db, struct ovsdb_log *log, { long long int now = time_msec(); struct ovsdb_file *file; + char *deref_name; char *abs_name; /* Use the absolute name of the file because ovsdb-server opens its * database before daemonize() chdirs to "/". */ - abs_name = abs_file_name(NULL, file_name); + deref_name = follow_symlinks(file_name); + abs_name = abs_file_name(NULL, deref_name); + free(deref_name); if (!abs_name) { *filep = NULL; return ovsdb_io_error(0, "could not determine current " @@ -512,7 +561,7 @@ ovsdb_file_create(struct ovsdb *db, struct ovsdb_log *log, static struct ovsdb_file * ovsdb_file_cast(struct ovsdb_replica *replica) { - assert(replica->class == &ovsdb_file_class); + ovs_assert(replica->class == &ovsdb_file_class); return CONTAINER_OF(replica, struct ovsdb_file, replica); } @@ -549,10 +598,10 @@ ovsdb_file_commit(struct ovsdb_replica *replica, } file->n_transactions++; - /* If it has been at least COMPACT_MIN_MSEC millseconds since the last time - * we compacted (or at least COMPACT_RETRY_MSEC since the last time we + /* If it has been at least COMPACT_MIN_MSEC ms since the last time we + * compacted (or at least COMPACT_RETRY_MSEC ms since the last time we * tried), and if there are at least 100 transactions in the database, and - * if the database is at least 1 MB, then compact the database. */ + * if the database is at least 10 MB, then compact the database. */ if (time_msec() >= file->next_compact && file->n_transactions >= 100 && ovsdb_log_get_offset(file->log) >= 10 * 1024 * 1024) @@ -562,7 +611,8 @@ ovsdb_file_commit(struct ovsdb_replica *replica, char *s = ovsdb_error_to_string(error); ovsdb_error_destroy(error); VLOG_WARN("%s: compacting database failed (%s), retrying in " - "60 seconds", file->file_name, s); + "%d seconds", + file->file_name, s, COMPACT_RETRY_MSEC / 1000); free(s); file->next_compact = time_msec() + COMPACT_RETRY_MSEC; @@ -598,7 +648,7 @@ ovsdb_file_compact(struct ovsdb_file *file) /* Lock temporary file. */ tmp_name = xasprintf("%s.tmp", file->file_name); - retval = lockfile_lock(tmp_name, 0, &tmp_lock); + retval = lockfile_lock(tmp_name, &tmp_lock); if (retval) { error = ovsdb_io_error(retval, "could not get lock on %s", tmp_name); goto exit;