diff --git a/archiver/ChangeLog b/archiver/ChangeLog index a53c1195a..600b79e10 100644 --- a/archiver/ChangeLog +++ b/archiver/ChangeLog @@ -1,5 +1,30 @@ +2001-05-04 Bradford Hovinen + + * cluster-location.c (cluster_location_do_rollback): Implement + + * location.c (location_do_rollback): Rename from do_rollback; make + into virtual method + (location_rollback_backend_to): + (location_rollback_backend_by): + (location_rollback_id): Update to call virtual method + + * Makefile.am (libximian_archiver_la_SOURCES): + (include_HEADERS): Add cluster.[ch], cluster-location.[ch] + 2001-05-03 Bradford Hovinen + * cluster.[ch]: New class + + * cluster.c (cluster_new): + (cluster_load): Implement + + * archive.c (archive_set_arg): Add argument ARG_IS_GLOBAL + (archive_class_init): Make ARG_PREFIX construct-only + (archive_construct): Implement + (do_load): Remove + (archive_load): Use archive_construct; pass is_global as an + argument to the object constructor + * location.c (location_store_xml): Support STORE_DEFAULT (store_snapshot_cb): Use STORE_DEFAULT rather than STORE_MASK_PREVIOUS diff --git a/archiver/Makefile.am b/archiver/Makefile.am index 8ebc620e0..0c3baf436 100644 --- a/archiver/Makefile.am +++ b/archiver/Makefile.am @@ -25,14 +25,22 @@ bin_PROGRAMS = ximian-archiver lib_LTLIBRARIES = libximian_archiver.la libximian_archiver_la_SOURCES = \ - archive.c archive.h \ - location.c location.h \ - config-log.c config-log.h \ - backend-list.c backend-list.h \ - util.c util.h + archive.c archive.h \ + location.c location.h \ + config-log.c config-log.h \ + backend-list.c backend-list.h \ + cluster.c cluster.h \ + cluster-location.c cluster-location.h \ + util.c util.h include_HEADERS = \ - archive.h location.h config-log.h backend-list.h util.h + archive.h \ + location.h \ + config-log.h \ + backend-list.h \ + cluster.h \ + cluster-location.h \ + util.h ximian_archiver_SOURCES = \ main.c diff --git a/archiver/archive.c b/archiver/archive.c index 461dc0cda..5ce505836 100644 --- a/archiver/archive.c +++ b/archiver/archive.c @@ -55,7 +55,8 @@ static Archive *global_archive; enum { ARG_0, - ARG_PREFIX + ARG_PREFIX, + ARG_IS_GLOBAL }; static void archive_init (Archive *archive); @@ -71,7 +72,6 @@ static void archive_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); -static gboolean do_load (Archive *archive); static void load_all_locations (Archive *archive); guint @@ -119,8 +119,12 @@ archive_class_init (ArchiveClass *klass) gtk_object_add_arg_type ("Archive::prefix", GTK_TYPE_POINTER, - GTK_ARG_READWRITE, + GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY, ARG_PREFIX); + gtk_object_add_arg_type ("Archive::is-global", + GTK_TYPE_INT, + GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY, + ARG_IS_GLOBAL); parent_class = gtk_type_class (gtk_object_get_type ()); } @@ -141,6 +145,13 @@ archive_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) if (GTK_VALUE_POINTER (*arg) != NULL) archive->prefix = g_strdup (GTK_VALUE_POINTER (*arg)); break; + + case ARG_IS_GLOBAL: + archive->is_global = GTK_VALUE_INT (*arg); + archive->backend_list = + BACKEND_LIST (backend_list_new (archive->is_global)); + break; + default: break; } @@ -161,12 +172,50 @@ archive_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) case ARG_PREFIX: GTK_VALUE_POINTER (*arg) = archive->prefix; break; + + case ARG_IS_GLOBAL: + GTK_VALUE_INT (*arg) = archive->is_global; + break; + default: arg->type = GTK_TYPE_INVALID; break; } } +/** + * archive_construct: + * @archive: + * @is_new: TRUE iff this is a new archive + * + * Load the archive information from disk + * + * Returns: TRUE on success and FALSE on failure + */ + +gboolean +archive_construct (Archive *archive, gboolean is_new) +{ + gint ret = 0; + + g_return_val_if_fail (archive != NULL, FALSE); + g_return_val_if_fail (IS_ARCHIVE (archive), FALSE); + g_return_val_if_fail (archive->prefix != NULL, FALSE); + + if (is_new) { + if (g_file_exists (archive->prefix)) + return FALSE; + + ret = mkdir (archive->prefix, S_IREAD | S_IWRITE | S_IEXEC); + if (ret == -1) return FALSE; + } else { + if (!g_file_test (archive->prefix, G_FILE_TEST_ISDIR)) + return FALSE; + } + + return TRUE; +} + /** * archive_load: * @is_global: TRUE iff we should load the global archive @@ -195,20 +244,19 @@ archive_load (gboolean is_global) object = gtk_object_new (archive_get_type (), "prefix", prefix, + "is-global", is_global, NULL); if (!is_global) g_free (prefix); - if (do_load (ARCHIVE (object)) == FALSE) { + if (archive_construct (ARCHIVE (object), FALSE) == FALSE && + archive_construct (ARCHIVE (object), TRUE) == FALSE) + { gtk_object_destroy (object); return NULL; } - ARCHIVE (object)->is_global = is_global; - ARCHIVE (object)->backend_list = - BACKEND_LIST (backend_list_new (is_global)); - if (is_global) global_archive = ARCHIVE (object); else @@ -595,27 +643,6 @@ archive_foreach_child_location (Archive *archive, LocationCB callback, &f_data); } -/* Load the archive information from disk; return TRUE on success and FALSE on - * failure - */ - -static gboolean -do_load (Archive *archive) -{ - gint ret = 0; - - g_return_val_if_fail (archive != NULL, FALSE); - g_return_val_if_fail (IS_ARCHIVE (archive), FALSE); - g_return_val_if_fail (archive->prefix != NULL, FALSE); - - if (g_file_test (archive->prefix, G_FILE_TEST_ISDIR) == FALSE) - ret = mkdir (archive->prefix, S_IREAD | S_IWRITE | S_IEXEC); - - if (ret == -1) return FALSE; - - return TRUE; -} - /* Load and register all the locations for this archive */ static void diff --git a/archiver/archive.h b/archiver/archive.h index 11816aef5..1f4162464 100644 --- a/archiver/archive.h +++ b/archiver/archive.h @@ -56,6 +56,9 @@ struct _ArchiveClass guint archive_get_type (void); +gboolean archive_construct (Archive *archive, + gboolean is_new); + GtkObject *archive_load (gboolean is_global); void archive_close (Archive *archive); diff --git a/archiver/cluster-location.c b/archiver/cluster-location.c new file mode 100644 index 000000000..1458261f9 --- /dev/null +++ b/archiver/cluster-location.c @@ -0,0 +1,222 @@ +/* -*- mode: c; style: linux -*- */ + +/* cluster-location.c + * Copyright (C) 2000 Ximian, Inc. + * + * Written by Bradford Hovinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "cluster.h" +#include "cluster-location.h" + +typedef struct _pair_t pair_t; + +enum { + ARG_0, + ARG_SAMPLE +}; + +struct _ClusterLocationPrivate +{ + /* Private data members */ +}; + +struct _pair_t +{ + gpointer a, b; +}; + +static LocationClass *parent_class; + +static void cluster_location_init (ClusterLocation *cluster_location); +static void cluster_location_class_init (ClusterLocationClass *class); + +static void cluster_location_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void cluster_location_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); + +static void cluster_location_finalize (GtkObject *object); + +static gboolean cluster_location_do_rollback (Location *location, + gchar *backend_id, + xmlDocPtr doc); + +static gboolean host_cb (Cluster *cluster, + gchar *hostname, + pair_t *pair); + +guint +cluster_location_get_type (void) +{ + static guint cluster_location_type = 0; + + if (!cluster_location_type) { + GtkTypeInfo cluster_location_info = { + "ClusterLocation", + sizeof (ClusterLocation), + sizeof (ClusterLocationClass), + (GtkClassInitFunc) cluster_location_class_init, + (GtkObjectInitFunc) cluster_location_init, + (GtkArgSetFunc) NULL, + (GtkArgGetFunc) NULL + }; + + cluster_location_type = + gtk_type_unique (location_get_type (), + &cluster_location_info); + } + + return cluster_location_type; +} + +static void +cluster_location_init (ClusterLocation *cluster_location) +{ + cluster_location->p = g_new0 (ClusterLocationPrivate, 1); +} + +static void +cluster_location_class_init (ClusterLocationClass *class) +{ + GtkObjectClass *object_class; + LocationClass *location_class; + + gtk_object_add_arg_type ("ClusterLocation::sample", + GTK_TYPE_POINTER, + GTK_ARG_READWRITE, + ARG_SAMPLE); + + object_class = GTK_OBJECT_CLASS (class); + object_class->finalize = cluster_location_finalize; + object_class->set_arg = cluster_location_set_arg; + object_class->get_arg = cluster_location_get_arg; + + location_class = LOCATION_CLASS (class); + location_class->do_rollback = cluster_location_do_rollback; + + parent_class = LOCATION_CLASS + (gtk_type_class (location_get_type ())); +} + +static void +cluster_location_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ClusterLocation *cluster_location; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CLUSTER_LOCATION (object)); + + cluster_location = CLUSTER_LOCATION (object); + + switch (arg_id) { + case ARG_SAMPLE: + break; + + default: + g_warning ("Bad argument set"); + break; + } +} + +static void +cluster_location_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ClusterLocation *cluster_location; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CLUSTER_LOCATION (object)); + + cluster_location = CLUSTER_LOCATION (object); + + switch (arg_id) { + case ARG_SAMPLE: + break; + + default: + g_warning ("Bad argument get"); + break; + } +} + +static void +cluster_location_finalize (GtkObject *object) +{ + ClusterLocation *cluster_location; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CLUSTER_LOCATION (object)); + + cluster_location = CLUSTER_LOCATION (object); + + g_free (cluster_location->p); + + GTK_OBJECT_CLASS (parent_class)->finalize (object); +} + +GtkObject * +cluster_location_new (void) +{ + return gtk_object_new (cluster_location_get_type (), + NULL); +} + +static gboolean +cluster_location_do_rollback (Location *location, gchar *backend_id, + xmlDocPtr doc) +{ + Cluster *cluster; + pair_t pair; + + g_return_val_if_fail (location != NULL, FALSE); + g_return_val_if_fail (IS_CLUSTER_LOCATION (location), FALSE); + g_return_val_if_fail (backend_id != NULL, FALSE); + g_return_val_if_fail (doc != NULL, FALSE); + + gtk_object_get (GTK_OBJECT (location), "archive", &cluster, NULL); + pair.a = doc; + pair.b = backend_id; + cluster_foreach_host (cluster, (ClusterHostCB) host_cb, &pair); + + return TRUE; +} + +static gboolean +host_cb (Cluster *cluster, gchar *hostname, pair_t *pair) +{ + xmlDocPtr doc; + gchar *backend_id, *command; + FILE *output; + + doc = pair->a; + backend_id = pair->b; + command = g_strconcat ("ssh ", hostname, " ", backend_id, " --set", + NULL); + output = popen (command, "w"); + xmlDocDump (output, doc); + pclose (output); + g_free (command); + + return FALSE; +} diff --git a/archiver/cluster-location.h b/archiver/cluster-location.h new file mode 100644 index 000000000..66592fcc3 --- /dev/null +++ b/archiver/cluster-location.h @@ -0,0 +1,59 @@ +/* -*- mode: c; style: linux -*- */ + +/* cluster-location.h + * Copyright (C) 2000 Ximian, Inc. + * + * Written by Bradford Hovinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef __CLUSTER_LOCATION_H +#define __CLUSTER_LOCATION_H + +#include + +#include "location.h" + +BEGIN_GNOME_DECLS + +#define CLUSTER_LOCATION(obj) GTK_CHECK_CAST (obj, cluster_location_get_type (), ClusterLocation) +#define CLUSTER_LOCATION_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, cluster_location_get_type (), ClusterLocationClass) +#define IS_CLUSTER_LOCATION(obj) GTK_CHECK_TYPE (obj, cluster_location_get_type ()) + +typedef struct _ClusterLocation ClusterLocation; +typedef struct _ClusterLocationClass ClusterLocationClass; +typedef struct _ClusterLocationPrivate ClusterLocationPrivate; + +struct _ClusterLocation +{ + Location parent; + + ClusterLocationPrivate *p; +}; + +struct _ClusterLocationClass +{ + LocationClass location_class; +}; + +guint cluster_location_get_type (void); + +GtkObject *cluster_location_new (void); + +END_GNOME_DECLS + +#endif /* __CLUSTER_LOCATION_H */ diff --git a/archiver/cluster.c b/archiver/cluster.c new file mode 100644 index 000000000..c9749b167 --- /dev/null +++ b/archiver/cluster.c @@ -0,0 +1,437 @@ +/* -*- mode: c; style: linux -*- */ + +/* cluster.c + * Copyright (C) 2000 Ximian, Inc. + * + * Written by Bradford Hovinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "cluster.h" + +enum { + ARG_0, + ARG_SAMPLE +}; + +typedef struct _SlaveHost SlaveHost; + +struct _SlaveHost +{ + gchar *hostname; +}; + +struct _ClusterPrivate +{ + GList *slave_hosts; +}; + +static ArchiveClass *parent_class; + +static void cluster_init (Cluster *cluster); +static void cluster_class_init (ClusterClass *class); + +static void cluster_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void cluster_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); + +static void cluster_destroy (GtkObject *object); +static void cluster_finalize (GtkObject *object); + +static gboolean cluster_construct (Cluster *cluster, + gboolean is_new); + +static gboolean load_metadata (Cluster *cluster); +static void save_metadata (Cluster *cluster); + +static void cluster_add_slave_host (Cluster *cluster, + SlaveHost *slave_host); +static void cluster_remove_slave_host (Cluster *cluster, + SlaveHost *slave_host); + +static SlaveHost *find_slave_host (Cluster *cluster, + gchar *hostname); +static gchar *get_metadata_filename (Cluster *cluster); + +static SlaveHost *slave_host_new (gchar *hostname); +static SlaveHost *slave_host_read_xml (xmlNodePtr node); +static xmlNodePtr slave_host_write_xml (SlaveHost *host); + +guint +cluster_get_type (void) +{ + static guint cluster_type = 0; + + if (!cluster_type) { + GtkTypeInfo cluster_info = { + "Cluster", + sizeof (Cluster), + sizeof (ClusterClass), + (GtkClassInitFunc) cluster_class_init, + (GtkObjectInitFunc) cluster_init, + (GtkArgSetFunc) NULL, + (GtkArgGetFunc) NULL + }; + + cluster_type = + gtk_type_unique (archive_get_type (), + &cluster_info); + } + + return cluster_type; +} + +static void +cluster_init (Cluster *cluster) +{ + cluster->p = g_new0 (ClusterPrivate, 1); +} + +static void +cluster_class_init (ClusterClass *class) +{ + GtkObjectClass *object_class; + + gtk_object_add_arg_type ("Cluster::sample", + GTK_TYPE_POINTER, + GTK_ARG_READWRITE, + ARG_SAMPLE); + + object_class = GTK_OBJECT_CLASS (class); + object_class->destroy = cluster_destroy; + object_class->finalize = cluster_finalize; + object_class->set_arg = cluster_set_arg; + object_class->get_arg = cluster_get_arg; + + parent_class = ARCHIVE_CLASS + (gtk_type_class (archive_get_type ())); +} + +static void +cluster_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + Cluster *cluster; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CLUSTER (object)); + + cluster = CLUSTER (object); + + switch (arg_id) { + case ARG_SAMPLE: + break; + + default: + g_warning ("Bad argument set"); + break; + } +} + +static void +cluster_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + Cluster *cluster; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CLUSTER (object)); + + cluster = CLUSTER (object); + + switch (arg_id) { + case ARG_SAMPLE: + break; + + default: + g_warning ("Bad argument get"); + break; + } +} + +static void +cluster_destroy (GtkObject *object) +{ + Cluster *cluster; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CLUSTER (object)); + + cluster = CLUSTER (object); + + save_metadata (cluster); + + GTK_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +cluster_finalize (GtkObject *object) +{ + Cluster *cluster; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CLUSTER (object)); + + cluster = CLUSTER (object); + + g_free (cluster->p); + + GTK_OBJECT_CLASS (parent_class)->finalize (object); +} + +GtkObject * +cluster_new (gchar *prefix) +{ + GtkObject *object; + + object = gtk_object_new (cluster_get_type (), + "prefix", prefix, + "is-global", TRUE, + NULL); + + if (cluster_construct (CLUSTER (object), TRUE) == FALSE) { + gtk_object_destroy (object); + return NULL; + } + + return object; +} + +GtkObject * +cluster_load (gchar *prefix) +{ + GtkObject *object; + + object = gtk_object_new (cluster_get_type (), + "prefix", prefix, + "is-global", TRUE, + NULL); + + if (cluster_construct (CLUSTER (object), FALSE) == FALSE) { + gtk_object_destroy (object); + return NULL; + } + + return object; +} + +void +cluster_foreach_host (Cluster *cluster, ClusterHostCB callback, gpointer data) +{ + GList *node; + SlaveHost *host; + + g_return_if_fail (cluster != NULL); + g_return_if_fail (IS_CLUSTER (cluster)); + g_return_if_fail (callback != NULL); + + for (node = cluster->p->slave_hosts; node; node = node->next) { + host = node->data; + if (callback (cluster, host->hostname, data)) break; + } +} + +void +cluster_add_host (Cluster *cluster, gchar *hostname) +{ + g_return_if_fail (cluster != NULL); + g_return_if_fail (IS_CLUSTER (cluster)); + g_return_if_fail (hostname != NULL); + + cluster_add_slave_host (cluster, slave_host_new (hostname)); +} + +void +cluster_remove_host (Cluster *cluster, gchar *hostname) +{ + g_return_if_fail (cluster != NULL); + g_return_if_fail (IS_CLUSTER (cluster)); + g_return_if_fail (hostname != NULL); + + cluster_remove_slave_host (cluster, + find_slave_host (cluster, hostname)); +} + +static gboolean +cluster_construct (Cluster *cluster, gboolean is_new) +{ + if (archive_construct (ARCHIVE (cluster), is_new) == FALSE) + return FALSE; + + if (!is_new) { + if (load_metadata (cluster) == FALSE) + return FALSE; + } + + return TRUE; +} + +/* Loads the metadata associated with the cluster; returns TRUE on success and + * FALSE on failure + */ + +static gboolean +load_metadata (Cluster *cluster) +{ + xmlDocPtr doc; + xmlNodePtr root_node, node; + gchar *filename; + SlaveHost *new_host; + + filename = get_metadata_filename (cluster); + doc = xmlParseFile (filename); + g_free (filename); + + if (doc == NULL) return FALSE; + + root_node = xmlDocGetRootElement (doc); + if (strcmp (root_node->name, "cluster")) { + xmlFreeDoc (doc); + return FALSE; + } + + for (node = root_node->childs; node != NULL; node = node->next) { + if (!strcmp (node->name, "host")) { + new_host = slave_host_read_xml (node); + if (new_host != NULL) + cluster_add_slave_host (cluster, new_host); + } + } + + xmlFreeDoc (doc); + + return TRUE; +} + +static void +save_metadata (Cluster *cluster) +{ + xmlDocPtr doc; + xmlNodePtr root_node; + GList *list_node; + gchar *filename; + + doc = xmlNewDoc ("1.0"); + root_node = xmlNewDocNode (doc, NULL, "cluster", NULL); + + for (list_node = cluster->p->slave_hosts; list_node != NULL; + list_node = list_node->next) + { + xmlAddChild (root_node, + slave_host_write_xml (list_node->data)); + } + + xmlDocSetRootElement (doc, root_node); + + filename = get_metadata_filename (cluster); + xmlSaveFile (filename, doc); + g_free (filename); +} + +/* Adds a slave host to the list of slave hosts for this cluster */ + +static void +cluster_add_slave_host (Cluster *cluster, SlaveHost *slave_host) +{ + if (slave_host == NULL) return; + + cluster->p->slave_hosts = + g_list_append (cluster->p->slave_hosts, slave_host); +} + +static void +cluster_remove_slave_host (Cluster *cluster, SlaveHost *slave_host) +{ + if (slave_host == NULL) return; + + cluster->p->slave_hosts = + g_list_remove (cluster->p->slave_hosts, slave_host); +} + +static SlaveHost * +find_slave_host (Cluster *cluster, gchar *hostname) +{ + SlaveHost *host; + GList *node; + + g_return_val_if_fail (hostname != NULL, NULL); + + for (node = cluster->p->slave_hosts; node != NULL; node = node->next) { + host = node->data; + + if (!strcmp (host->hostname, hostname)) + return host; + } + + return NULL; +} + +/* Returns the filename of the metadata file (should be freed after use) */ + +static gchar * +get_metadata_filename (Cluster *cluster) +{ + return g_concat_dir_and_file + (archive_get_prefix (ARCHIVE (cluster)), "cluster.xml"); +} + +/* Constructs a new slave host structure */ + +static SlaveHost * +slave_host_new (gchar *hostname) +{ + SlaveHost *new_host; + + new_host = g_new0 (SlaveHost, 1); + new_host->hostname = g_strdup (hostname); + + return new_host; +} + +/* Constructs a new slave host structure from an XML node */ + +static SlaveHost * +slave_host_read_xml (xmlNodePtr node) +{ + gchar *hostname; + + hostname = xmlGetProp (node, "name"); + + if (hostname != NULL) + return slave_host_new (hostname); + else + return NULL; +} + +/* Constructs an XML node for the slave host */ + +static xmlNodePtr +slave_host_write_xml (SlaveHost *host) +{ + xmlNodePtr node; + + node = xmlNewNode (NULL, "host"); + xmlNewProp (node, "name", host->hostname); + return node; +} diff --git a/archiver/cluster.h b/archiver/cluster.h new file mode 100644 index 000000000..223852019 --- /dev/null +++ b/archiver/cluster.h @@ -0,0 +1,71 @@ +/* -*- mode: c; style: linux -*- */ + +/* cluster.h + * Copyright (C) 2000 Ximian, Inc. + * + * Written by Bradford Hovinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef __CLUSTER_H +#define __CLUSTER_H + +#include + +#include "archive.h" + +BEGIN_GNOME_DECLS + +#define CLUSTER(obj) GTK_CHECK_CAST (obj, cluster_get_type (), Cluster) +#define CLUSTER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, cluster_get_type (), ClusterClass) +#define IS_CLUSTER(obj) GTK_CHECK_TYPE (obj, cluster_get_type ()) + +typedef struct _Cluster Cluster; +typedef struct _ClusterClass ClusterClass; +typedef struct _ClusterPrivate ClusterPrivate; + +typedef gboolean (*ClusterHostCB) (Cluster *, gchar *, gpointer); + +struct _Cluster +{ + Archive parent; + + ClusterPrivate *p; +}; + +struct _ClusterClass +{ + ArchiveClass archive_class; +}; + +guint cluster_get_type (void); + +GtkObject *cluster_new (gchar *prefix); +GtkObject *cluster_load (gchar *prefix); + +void cluster_foreach_host (Cluster *cluster, + ClusterHostCB callback, + gpointer data); + +void cluster_add_host (Cluster *cluster, + gchar *hostname); +void cluster_remove_host (Cluster *cluster, + gchar *hostname); + +END_GNOME_DECLS + +#endif /* __CLUSTER_H */ diff --git a/archiver/location.c b/archiver/location.c index 48c5f6430..3d66a5d19 100644 --- a/archiver/location.c +++ b/archiver/location.c @@ -73,56 +73,60 @@ struct _LocationPrivate ConfigLog *config_log; }; -static void location_init (Location *location); -static void location_class_init (LocationClass *klass); +static void location_init (Location *location); +static void location_class_init (LocationClass *klass); -static void location_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); +static void location_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); -static void location_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); +static void location_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); -static void location_destroy (GtkObject *object); -static void location_finalize (GtkObject *object); +static void location_destroy (GtkObject *object); +static void location_finalize (GtkObject *object); -static gint store_snapshot_cb (Location *location, - gchar *backend_id); +static gboolean location_do_rollback (Location *location, + gchar *backend_id, + xmlDocPtr xml_doc); -static gint get_backends_cb (BackendList *backend_list, - gchar *backend_id, - Location *location); +static gint store_snapshot_cb (Location *location, + gchar *backend_id); -static gboolean do_create (Location *location); -static gboolean do_load (Location *location); -static gboolean load_metadata_file (Location *location, - char *filename, - gboolean is_default); -static void save_metadata (Location *location); -static void write_metadata_file (Location *location, - gchar *filename); +static gint get_backends_cb (BackendList *backend_list, + gchar *backend_id, + Location *location); -static gboolean do_rollback (gchar *backend_id, - xmlDocPtr xml_doc); -static xmlDocPtr load_xml_data (gchar *fullpath, gint id); -static gint run_backend_proc (gchar *backend_id, - gboolean do_get); +static gboolean do_create (Location *location); +static gboolean do_load (Location *location); +static gboolean load_metadata_file (Location *location, + char *filename, + gboolean is_default); +static void save_metadata (Location *location); +static void write_metadata_file (Location *location, + gchar *filename); + +static xmlDocPtr load_xml_data (gchar *fullpath, gint id); +static gint run_backend_proc (gchar *backend_id, + gboolean do_get); static BackendNote *backend_note_new (gchar *backend_id, ContainmentType type); static void backend_note_destroy (BackendNote *note); static const BackendNote *find_note (Location *location, gchar *backend_id); -static void merge_xml_docs (xmlDocPtr child_doc, - xmlDocPtr parent_doc); -static void subtract_xml_doc (xmlDocPtr child_doc, - xmlDocPtr parent_doc, - gboolean strict); -static void merge_xml_nodes (xmlNodePtr node1, xmlNodePtr node2); -static xmlNodePtr subtract_xml_node (xmlNodePtr node1, xmlNodePtr node2, - gboolean strict); -static gboolean compare_xml_nodes (xmlNodePtr node1, xmlNodePtr node2); +static void merge_xml_docs (xmlDocPtr child_doc, + xmlDocPtr parent_doc); +static void subtract_xml_doc (xmlDocPtr child_doc, + xmlDocPtr parent_doc, + gboolean strict); +static void merge_xml_nodes (xmlNodePtr node1, + xmlNodePtr node2); +static xmlNodePtr subtract_xml_node (xmlNodePtr node1, + xmlNodePtr node2, + gboolean strict); +static gboolean compare_xml_nodes (xmlNodePtr node1, xmlNodePtr node2); guint location_get_type (void) @@ -185,6 +189,8 @@ location_class_init (LocationClass *klass) GTK_ARG_READWRITE, ARG_INHERITS); + klass->do_rollback = location_do_rollback; + parent_class = gtk_type_class (gtk_object_get_type ()); } @@ -378,6 +384,38 @@ location_finalize (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->finalize (object); } +/* Perform rollback for a given backend and id number. Return TRUE on + * success and FALSE otherwise. + * + * FIXME: Better error reporting + */ + +static gboolean +location_do_rollback (Location *location, gchar *backend_id, xmlDocPtr doc) +{ + int fd; + FILE *output; + + g_return_val_if_fail (location != NULL, FALSE); + g_return_val_if_fail (IS_LOCATION (location), FALSE); + g_return_val_if_fail (backend_id != NULL, FALSE); + g_return_val_if_fail (doc != NULL, FALSE); + + /* FIXME: Some mechanism for retrieving the factory defaults settings + * would be useful here + */ + if (doc == NULL) return FALSE; + + fd = run_backend_proc (backend_id, FALSE); + if (fd == -1) return FALSE; + + output = fdopen (fd, "w"); + xmlDocDump (output, doc); + fclose (output); + + return TRUE; +} + /** * location_close: * @location: @@ -592,7 +630,8 @@ location_rollback_backend_to (Location *location, struct tm *date, doc = location_load_rollback_data (location, date, 0, backend_id, parent_chain); - do_rollback (backend_id, doc); + LOCATION_CLASS (GTK_OBJECT (location)->klass)->do_rollback + (location, backend_id, doc); xmlFreeDoc (doc); } @@ -678,7 +717,8 @@ location_rollback_backend_by (Location *location, guint steps, doc = location_load_rollback_data (location, NULL, steps, backend_id, parent_chain); - do_rollback (backend_id, doc); + LOCATION_CLASS (GTK_OBJECT (location)->klass)->do_rollback + (location, backend_id, doc); xmlFreeDoc (doc); } @@ -716,7 +756,8 @@ location_rollback_id (Location *location, gint id) } if (backend_id) - do_rollback (backend_id, xml_doc); + LOCATION_CLASS (GTK_OBJECT (location)->klass)->do_rollback + (location, backend_id, xml_doc); } /** @@ -1392,33 +1433,6 @@ write_metadata_file (Location *location, gchar *filename) xmlFreeDoc (doc); } -/* Perform rollback for a given backend and id number. Return TRUE on - * success and FALSE otherwise. - * - * FIXME: Better error reporting - */ - -static gboolean -do_rollback (gchar *backend_id, xmlDocPtr doc) -{ - int fd; - FILE *output; - - /* FIXME: Some mechanism for retrieving the factory defaults settings - * would be useful here - */ - if (doc == NULL) return FALSE; - - fd = run_backend_proc (backend_id, FALSE); - if (fd == -1) return FALSE; - - output = fdopen (fd, "w"); - xmlDocDump (output, doc); - fclose (output); - - return TRUE; -} - static xmlDocPtr load_xml_data (gchar *fullpath, gint id) { diff --git a/archiver/location.h b/archiver/location.h index edfc5d6ee..4960a5c00 100644 --- a/archiver/location.h +++ b/archiver/location.h @@ -52,6 +52,10 @@ struct _Location struct _LocationClass { GtkObjectClass parent; + + gboolean (*do_rollback) (Location *location, + gchar *backend_id, + xmlDocPtr xml_doc); }; enum _ContainmentType