Added CORBA interface to the archiver

This commit is contained in:
Bradford Hovinen (Gdict maintainer) 2001-08-20 15:47:57 +00:00
parent 7c531bc29e
commit 4e6a3b89d6
28 changed files with 2258 additions and 1121 deletions

View file

@ -1,4 +1,4 @@
SUBDIRS = archiver capplets control-center po intl
SUBDIRS = archiver capplets control-center idl po intl
#I removed the root-manager for now
#
# it generated this error :

View file

@ -8,7 +8,7 @@
<oaf_attribute name="name" type="string" value="XML Database Moniker factory"/>
</oaf_server>
<oaf_server iid="OAFIID:Bonobo_Moniker_archiver" type="factory"
<oaf_server iid="OAFIID:Bonobo_Moniker_archiverdb" type="factory"
location="OAFIID:Bonobo_Moniker_archiver_Factory">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Bonobo/Moniker:1.0"/>
@ -16,7 +16,19 @@
</oaf_attribute>
<oaf_attribute name="name" type="string" value="XML Database Moniker with archiver interface"/>
<oaf_attribute name="bonobo:moniker" type="stringv">
<item value="archiver:"/>
<item value="archiverdb:"/>
</oaf_attribute>
</oaf_server>
<oaf_server iid="OAFIID:Bonobo_Moniker_archive" type="factory"
location="OAFIID:Bonobo_Moniker_archiver_Factory">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Bonobo/Moniker:1.0"/>
<item value="IDL:Bonobo/Unknown:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="XML archiver interface"/>
<oaf_attribute name="bonobo:moniker" type="stringv">
<item value="archive:"/>
</oaf_attribute>
</oaf_server>

View file

@ -1,3 +1,13 @@
2001-08-17 Bradford Hovinen <hovinen@ximian.com>
* all: Added CORBA interface for the archiver
* config-archiver.c: Ported to new CORBA interface
2001-08-20 Bradford Hovinen <hovinen@ximian.com>
* location.c (load_metadata_file): Support placing the location's
label in the metadata file
2001-08-03 Bradford Hovinen <hovinen@ximian.com>
* config-log.c (load_log_entry): Return NULL if fgets returns NULL

View file

@ -20,39 +20,35 @@ INCLUDES = \
@ARCHIVER_CFLAGS@ \
@MONIKER_CFLAGS@
if MONIKER_ENABLE
BONOBO_MONIKER_ARCHIVER_BIN=bonobo-moniker-archiver
else
BONOBO_MONIKER_ARCHIVER_BIN=
endif
CORBA_SOURCE = \
ConfigArchiver.h \
ConfigArchiver-common.c \
ConfigArchiver-stubs.c \
ConfigArchiver-skels.c
bin_PROGRAMS = $(BONOBO_MONIKER_ARCHIVER_BIN) config-archiver
idl_flags = `gnome-config --cflags idl`
$(CORBA_SOURCE): $(top_srcdir)/idl/ConfigArchiver.idl
orbit-idl $(top_srcdir)/idl/ConfigArchiver.idl -I$(top_srcdir)/idl $(idl_flags)
bin_PROGRAMS = bonobo-moniker-archiver config-archiver
lib_LTLIBRARIES = libconfig_archiver.la
libconfig_archiver_la_SOURCES = \
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
util.c util.h \
archiver-client.c \
$(CORBA_SOURCE)
libconfig_archiver_la_LIBADD = \
@GNOME_XML_LIBS@
include_HEADERS = \
archive.h \
location.h \
config-log.h \
backend-list.h \
cluster.h \
cluster-location.h \
util.h
ConfigArchiver.h \
archiver-client.h
config_archiver_SOURCES = \
main.c
config-archiver.c
config_archiver_LDADD = \
$(GNOME_LIBDIR) \
@ -87,9 +83,14 @@ Bonobo_Moniker_archiver.oaf : $(srcdir)/Bonobo_Moniker_archiver.oaf.in $(top_bui
clean-local:
-rm -f $(OAF_FILES)
bonobo_moniker_archiver_SOURCES = \
bonobo-config-archiver.c \
bonobo-config-archiver.h \
bonobo_moniker_archiver_SOURCES = \
bonobo-config-archiver.c bonobo-config-archiver.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 \
bonobo-moniker-archiver.c
bonobo_moniker_archiver_LDADD = @MONIKER_LIBS@ libconfig_archiver.la

View file

@ -35,9 +35,6 @@
#include "archive.h"
#include "util.h"
typedef struct _GRealTree GRealTree;
typedef struct _GTreeNode GTreeNode;
typedef struct _foreach_t foreach_t;
struct _foreach_t
@ -50,15 +47,14 @@ struct _foreach_t
static GtkObjectClass *parent_class;
static Archive *user_archive;
static Archive *global_archive;
enum {
ARG_0,
ARG_PREFIX,
ARG_IS_GLOBAL
};
#define ARCHIVE_FROM_SERVANT(servant) (ARCHIVE (bonobo_object_from_servant (servant)))
static void archive_init (Archive *archive);
static void archive_class_init (ArchiveClass *klass);
@ -74,30 +70,129 @@ static void archive_get_arg (GtkObject *object,
static void load_all_locations (Archive *archive);
guint
archive_get_type (void)
/* CORBA interface methods */
static ConfigArchiver_Location
impl_ConfigArchiver_Archive_getLocation (PortableServer_Servant servant,
const CORBA_char *locid,
CORBA_Environment *ev)
{
static guint archive_type;
if (!archive_type) {
GtkTypeInfo archive_info = {
"Archive",
sizeof (Archive),
sizeof (ArchiveClass),
(GtkClassInitFunc) archive_class_init,
(GtkObjectInitFunc) archive_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
archive_type =
gtk_type_unique (gtk_object_get_type (),
&archive_info);
}
return archive_type;
return CORBA_Object_duplicate (BONOBO_OBJREF (archive_get_location (ARCHIVE_FROM_SERVANT (servant), locid)), ev);
}
static ConfigArchiver_Location
impl_ConfigArchiver_Archive_createLocation (PortableServer_Servant servant,
const CORBA_char *locid,
const CORBA_char *label,
const ConfigArchiver_Location parent_ref,
CORBA_Environment *ev)
{
Location *loc;
loc = archive_create_location (ARCHIVE_FROM_SERVANT (servant), locid, label,
LOCATION (bonobo_object_from_servant (parent_ref)));
return bonobo_object_dup_ref (BONOBO_OBJREF (loc), ev);
}
static void
build_list_cb (Archive *archive, Location *location, GList **list)
{
*list = g_list_prepend (*list, bonobo_object_dup_ref (BONOBO_OBJREF (location), NULL));
}
static ConfigArchiver_LocationSeq *
impl_ConfigArchiver_Archive_getChildLocations (PortableServer_Servant servant,
ConfigArchiver_Location location_ref,
CORBA_Environment *ev)
{
ConfigArchiver_LocationSeq *ret;
Archive *archive;
Location *location;
GList *locs = NULL, *tmp;
guint i = 0;
archive = ARCHIVE_FROM_SERVANT (servant);
if (location_ref == CORBA_OBJECT_NIL)
location = NULL;
else
location = LOCATION (bonobo_object_from_servant (location_ref->servant));
archive_foreach_child_location (archive, (LocationCB) build_list_cb, location, &locs);
ret = ConfigArchiver_LocationSeq__alloc ();
ret->_length = g_list_length (locs);
ret->_buffer = CORBA_sequence_ConfigArchiver_Location_allocbuf (ret->_length);
for (tmp = locs; tmp != NULL; tmp = tmp->next)
ret->_buffer[i++] = tmp->data;
g_list_free (locs);
return ret;
}
static CORBA_char *
impl_ConfigArchiver_Archive__get_prefix (PortableServer_Servant servant,
CORBA_Environment *ev)
{
return CORBA_string_dup (ARCHIVE_FROM_SERVANT (servant)->prefix);
}
static CORBA_boolean
impl_ConfigArchiver_Archive__get_isGlobal (PortableServer_Servant servant,
CORBA_Environment *ev)
{
return ARCHIVE_FROM_SERVANT (servant)->is_global;
}
static ConfigArchiver_BackendList
impl_ConfigArchiver_Archive__get_backendList (PortableServer_Servant servant,
CORBA_Environment *ev)
{
return bonobo_object_dup_ref (BONOBO_OBJREF (ARCHIVE_FROM_SERVANT (servant)->backend_list), ev);
}
static ConfigArchiver_Location
impl_ConfigArchiver_Archive__get_currentLocation (PortableServer_Servant servant,
CORBA_Environment *ev)
{
return CORBA_Object_duplicate (BONOBO_OBJREF (archive_get_current_location (ARCHIVE_FROM_SERVANT (servant))), ev);
}
static void
impl_ConfigArchiver_Archive__set_currentLocation (PortableServer_Servant servant,
ConfigArchiver_Location location_ref,
CORBA_Environment *ev)
{
Archive *archive = ARCHIVE_FROM_SERVANT (servant);
Location *location;
location = LOCATION (bonobo_object_from_servant (location_ref->servant));
if (location == NULL)
/* bonobo_exception_set (ev, ex_ConfigArchiver_Archive_LocationNotFound) */;
else
archive_set_current_location (archive, location);
}
static void
impl_ConfigArchiver_Archive__set_currentLocationId (PortableServer_Servant servant,
const CORBA_char *locid,
CORBA_Environment *ev)
{
archive_set_current_location_id (ARCHIVE_FROM_SERVANT (servant), locid);
}
CORBA_char *
impl_ConfigArchiver_Archive__get_currentLocationId (PortableServer_Servant servant,
CORBA_Environment *ev)
{
return CORBA_string_dup (archive_get_current_location_id (ARCHIVE_FROM_SERVANT (servant)));
}
BONOBO_X_TYPE_FUNC_FULL (Archive, ConfigArchiver_Archive, BONOBO_X_OBJECT_TYPE, archive);
static void
archive_init (Archive *archive)
{
@ -126,7 +221,20 @@ archive_class_init (ArchiveClass *klass)
GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
ARG_IS_GLOBAL);
parent_class = gtk_type_class (gtk_object_get_type ());
klass->epv.getLocation = impl_ConfigArchiver_Archive_getLocation;
klass->epv.createLocation = impl_ConfigArchiver_Archive_createLocation;
klass->epv.getChildLocations = impl_ConfigArchiver_Archive_getChildLocations;
klass->epv._get_prefix = impl_ConfigArchiver_Archive__get_prefix;
klass->epv._get_isGlobal = impl_ConfigArchiver_Archive__get_isGlobal;
klass->epv._get_backendList = impl_ConfigArchiver_Archive__get_backendList;
klass->epv._get_currentLocation = impl_ConfigArchiver_Archive__get_currentLocation;
klass->epv._get_currentLocationId = impl_ConfigArchiver_Archive__get_currentLocationId;
klass->epv._set_currentLocation = impl_ConfigArchiver_Archive__set_currentLocation;
klass->epv._set_currentLocationId = impl_ConfigArchiver_Archive__set_currentLocationId;
parent_class = gtk_type_class (BONOBO_X_OBJECT_TYPE);
}
static void
@ -225,27 +333,22 @@ archive_construct (Archive *archive, gboolean is_new)
* Return value: Reference to archive
**/
GtkObject *
BonoboObject *
archive_load (gboolean is_global)
{
GtkObject *object;
BonoboObject *object;
gchar *prefix;
if (is_global && global_archive != NULL)
return GTK_OBJECT (global_archive);
else if (user_archive != NULL)
return GTK_OBJECT (user_archive);
if (is_global)
prefix = "/var/ximian-setup-tools";
else
prefix = g_concat_dir_and_file (g_get_home_dir (),
".gnome/capplet-archive");
object = gtk_object_new (archive_get_type (),
"prefix", prefix,
"is-global", is_global,
NULL);
object = BONOBO_OBJECT (gtk_object_new (archive_get_type (),
"prefix", prefix,
"is-global", is_global,
NULL));
if (!is_global)
g_free (prefix);
@ -253,22 +356,17 @@ archive_load (gboolean is_global)
if (archive_construct (ARCHIVE (object), FALSE) == FALSE &&
archive_construct (ARCHIVE (object), TRUE) == FALSE)
{
gtk_object_destroy (object);
bonobo_object_unref (object);
return NULL;
}
if (is_global)
global_archive = ARCHIVE (object);
else
user_archive = ARCHIVE (object);
return object;
}
static gint
free_location_cb (gchar *locid, Location *location)
free_location_cb (gchar *locid, BonoboObject *location)
{
location_close (location);
bonobo_object_unref (location);
g_free (locid);
return FALSE;
@ -296,36 +394,16 @@ archive_destroy (GtkObject *object)
if (archive->current_location_id != NULL)
g_free (archive->current_location_id);
GTK_OBJECT_CLASS (parent_class)->destroy (GTK_OBJECT (archive));
if (archive->backend_list != NULL)
bonobo_object_unref (BONOBO_OBJECT (archive->backend_list));
if (archive->is_global)
global_archive = NULL;
else
user_archive = NULL;
GTK_OBJECT_CLASS (parent_class)->destroy (GTK_OBJECT (archive));
DEBUG_MSG ("Exit");
}
/**
* archive_close:
* @archive:
*
* Closes the given archive handle. Also closes all locations under this
* archive.
**/
void
archive_close (Archive *archive)
{
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
gtk_object_destroy (GTK_OBJECT (archive));
}
/**
* archive_get_location:
* @archive:
* @locid:
*
* Get a reference to the location with the given name.
@ -334,57 +412,67 @@ archive_close (Archive *archive)
**/
Location *
archive_get_location (Archive *archive, const gchar *locid)
archive_get_location (Archive *archive,
const gchar *locid)
{
GtkObject *loc_obj;
Location *loc_obj;
gchar *tmp;
g_return_val_if_fail (archive != NULL, NULL);
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
g_return_val_if_fail (locid != NULL, NULL);
DEBUG_MSG ("Enter: %s", locid);
/* Stupid borken glib... */
tmp = g_strdup (locid);
loc_obj = g_tree_lookup (archive->locations, tmp);
g_free (tmp);
if (!loc_obj) {
loc_obj = location_open (archive, locid);
if (loc_obj == NULL) {
loc_obj = LOCATION (location_open (archive, locid));
if (!loc_obj) return NULL;
if (loc_obj)
if (loc_obj == NULL)
return NULL;
else
g_tree_insert (archive->locations,
g_strdup (locid), loc_obj);
} else {
bonobo_object_ref (BONOBO_OBJECT (loc_obj));
}
if (loc_obj) {
gtk_object_ref (loc_obj);
return LOCATION (loc_obj);
} else {
return NULL;
}
return loc_obj;
}
/**
* archive_register_location:
* @archive:
* @location:
*
* Register a location with the archive; invoked by location_new
**/
* archive_create_location:
* @archive:
* @location:
*
* Creates a new location
*/
void
archive_register_location (Archive *archive, Location *location)
Location *
archive_create_location (Archive *archive,
const gchar *locid,
const gchar *label,
Location *parent)
{
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
g_return_if_fail (location != NULL);
g_return_if_fail (IS_LOCATION (location));
Location *location;
g_tree_insert (archive->locations,
g_strdup (location_get_id (location)),
location);
g_return_val_if_fail (archive != NULL, NULL);
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
g_return_val_if_fail (locid != NULL, NULL);
g_return_val_if_fail (label != NULL, NULL);
g_return_val_if_fail (parent == NULL || IS_LOCATION (parent), NULL);
location = LOCATION (location_new (archive, locid, label, parent));
if (location == NULL)
return NULL;
g_tree_insert (archive->locations, g_strdup (locid), location);
return location;
}
/**
@ -406,7 +494,7 @@ archive_unregister_location (Archive *archive, Location *location)
g_return_if_fail (IS_LOCATION (location));
if (GTK_OBJECT_DESTROYED (archive)) return;
tmp = g_strdup (location_get_id (location));
g_tree_remove (archive->locations, tmp);
g_free (tmp);
@ -414,7 +502,6 @@ archive_unregister_location (Archive *archive, Location *location)
/**
* archive_get_current_location:
* @archive: object
*
* Convenience function to get a pointer to the current location
*
@ -425,11 +512,13 @@ archive_unregister_location (Archive *archive, Location *location)
Location *
archive_get_current_location (Archive *archive)
{
const gchar *locid = archive_get_current_location_id (archive);
const gchar *locid;
g_return_val_if_fail (archive != NULL, NULL);
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
locid = archive_get_current_location_id (archive);
if (locid == NULL)
return NULL;
else
@ -438,7 +527,6 @@ archive_get_current_location (Archive *archive)
/**
* archive_set_current_location:
* @archive: object
* @location: Location to which to set archive
*
* Set the current location in an archive to the location given; apply
@ -446,33 +534,35 @@ archive_get_current_location (Archive *archive)
**/
void
archive_set_current_location (Archive *archive, Location *location)
archive_set_current_location (Archive *archive,
Location *location)
{
Location *old_location;
GList *backends;
Location *old_location = archive_get_current_location (archive);
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
g_return_if_fail (location != NULL);
g_return_if_fail (IS_LOCATION (location));
old_location = archive_get_current_location (archive);
archive_set_current_location_id (archive, location_get_id (location));
backends = location_get_changed_backends (location, old_location);
location_rollback_backends_to (location, NULL, backends, TRUE);
g_list_free (backends);
location_rollback_backends_to (location, NULL, 0, backends, TRUE);
}
/**
* archive_set_current_location_id:
* @archive:
* @name:
*
* Sets the current location's name, but does not invoke any rollback
**/
void
archive_set_current_location_id (Archive *archive, const gchar *locid)
archive_set_current_location_id (Archive *archive,
const gchar *locid)
{
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
@ -497,7 +587,6 @@ archive_set_current_location_id (Archive *archive, const gchar *locid)
/**
* archive_get_current_location_id:
* @archive: object
*
* Get the name of the current location
*
@ -511,6 +600,7 @@ archive_get_current_location_id (Archive *archive)
{
gboolean def;
Location *loc;
Location *current_location;
g_return_val_if_fail (archive != NULL, NULL);
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
@ -526,18 +616,24 @@ archive_get_current_location_id (Archive *archive)
("/capplet-archive/config/current/location=default", &def);
/* Create default location if it does not exist */
if (def && archive_get_location
(archive, archive->current_location_id) == NULL)
{
loc = LOCATION
(location_new (archive,
archive->current_location_id,
NULL));
if (archive->is_global &&
location_store_full_snapshot (loc) < 0)
{
location_delete (loc);
return NULL;
if (def) {
current_location =
archive_get_location (archive, archive->current_location_id);
if (current_location == NULL) {
loc = LOCATION
(location_new (archive,
archive->current_location_id,
_("Default location"),
NULL));
if (archive->is_global &&
location_store_full_snapshot (loc) < 0)
{
location_delete (loc);
return NULL;
}
} else {
bonobo_object_unref (BONOBO_OBJECT (current_location));
}
}
}
@ -603,10 +699,11 @@ static gint
foreach_cb (gchar *key, Location *value, foreach_t *data)
{
if (location_get_parent (value) == data->parent)
return data->callback (data->archive, value,
data->user_data);
else
return 0;
data->callback (data->archive, value, data->user_data);
bonobo_object_unref (BONOBO_OBJECT (value));
return 0;
}
/**

View file

@ -26,6 +26,8 @@
#include <gnome.h>
#include "ConfigArchiver.h"
#include "location.h"
#include "backend-list.h"
@ -34,58 +36,62 @@
#define IS_ARCHIVE(obj) GTK_CHECK_TYPE (obj, archive_get_type ())
typedef struct _ArchiveClass ArchiveClass;
typedef gint (*LocationCB) (Archive *, Location *, gpointer);
typedef void (*LocationCB) (Archive *, Location *, gpointer);
struct _Archive
struct _Archive
{
GtkObject object;
BonoboXObject object;
gchar *prefix;
GTree *locations;
gboolean is_global;
gchar *prefix;
GTree *locations;
gboolean is_global;
gchar *current_location_id;
gchar *current_location_id;
BackendList *backend_list;
BackendList *backend_list;
};
struct _ArchiveClass
{
GtkObjectClass parent;
BonoboXObjectClass parent;
POA_ConfigArchiver_Archive__epv epv;
};
guint archive_get_type (void);
guint archive_get_type (void);
gboolean archive_construct (Archive *archive,
gboolean is_new);
gboolean archive_construct (Archive *archive,
gboolean is_new);
GtkObject *archive_load (gboolean is_global);
BonoboObject *archive_load (gboolean is_global);
void archive_close (Archive *archive);
void archive_close (Archive *archive);
Location *archive_get_location (Archive *archive,
const gchar *location);
void archive_register_location (Archive *archive,
Location *location);
void archive_unregister_location (Archive *archive,
Location *location);
Location *archive_get_location (Archive *archive,
const gchar *locid);
Location *archive_create_location (Archive *archive,
const gchar *locid,
const gchar *label,
Location *parent);
void archive_unregister_location (Archive *archive,
Location *location);
Location *archive_get_current_location (Archive *archive);
void archive_set_current_location (Archive *archive,
Location *location);
Location *archive_get_current_location (Archive *archive);
void archive_set_current_location (Archive *archive,
Location *location);
const gchar *archive_get_current_location_id (Archive *archive);
void archive_set_current_location_id (Archive *archive,
const gchar *locid);
const gchar *archive_get_current_location_id (Archive *archive);
void archive_set_current_location_id (Archive *archive,
const gchar *locid);
const gchar *archive_get_prefix (Archive *archive);
gboolean archive_is_global (Archive *archive);
const gchar *archive_get_prefix (Archive *archive);
gboolean archive_is_global (Archive *archive);
BackendList *archive_get_backend_list (Archive *archive);
BackendList *archive_get_backend_list (Archive *archive);
void archive_foreach_child_location (Archive *archive,
LocationCB callback,
Location *parent,
gpointer data);
void archive_foreach_child_location (Archive *archive,
LocationCB callback,
Location *parent,
gpointer data);
#endif /* __ARCHIVE */

422
archiver/archiver-client.c Normal file
View file

@ -0,0 +1,422 @@
/* -*- mode: c; style: linux -*- */
/* archiver-client.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* 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 <bonobo.h>
#include <gnome-xml/parser.h>
#include "archiver-client.h"
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);
/**
* location_load_rollback_data
* @location:
* @date:
* @steps:
* @backend_id:
* @parent_chain:
*
* Loads the XML data for rolling back as specified and returns the document
* object
**/
xmlDocPtr
location_client_load_rollback_data (ConfigArchiver_Location location,
struct tm *date,
guint steps,
gchar *backend_id,
gboolean parent_chain,
CORBA_Environment *opt_ev)
{
gchar *filename;
time_t time_g;
xmlDocPtr doc = NULL, parent_doc = NULL;
ConfigArchiver_ContainmentType type = ConfigArchiver_CONTAIN_FULL;
ConfigArchiver_Location parent = CORBA_OBJECT_NIL;
CORBA_Environment my_ev;
g_return_val_if_fail (location != CORBA_OBJECT_NIL, NULL);
if (opt_ev == NULL) {
opt_ev = &my_ev;
CORBA_exception_init (opt_ev);
}
if (date != NULL)
time_g = mktime (date);
else
time_g = 0;
filename = ConfigArchiver_Location_getRollbackFilename
(location, time_g, steps, backend_id, parent_chain, opt_ev);
if (filename != NULL)
doc = xmlParseFile (filename);
else if (parent_chain)
type = ConfigArchiver_Location_contains (location, backend_id, opt_ev);
if (type == ConfigArchiver_CONTAIN_PARTIAL)
parent = ConfigArchiver_Location__get_parent (location, opt_ev);
if (parent != CORBA_OBJECT_NIL) {
parent_doc = location_client_load_rollback_data
(parent, date, steps, backend_id, TRUE, opt_ev);
bonobo_object_release_unref (parent, NULL);
}
if (doc != NULL && parent_doc != NULL)
merge_xml_docs (doc, parent_doc);
else if (parent_doc != NULL)
doc = parent_doc;
if (opt_ev == &my_ev)
CORBA_exception_free (opt_ev);
return doc;
}
/**
* location_client_store_xml:
* @location:
* @backend_id:
* @input:
* @store_type: STORE_FULL means blindly store the data, without
* modification. STORE_COMPARE_PARENT means subtract the settings the parent
* has that are different and store the result. STORE_MASK_PREVIOUS means
* store only those settings that are reflected in the previous logged data;
* if there do not exist such data, act as in STORE_COMPARE_PARENT
* @opt_ev:
*
* Store configuration data from the given XML document object in the location
* under the given backend id
**/
void
location_client_store_xml (ConfigArchiver_Location location,
gchar *backend_id,
xmlDocPtr xml_doc,
ConfigArchiver_StoreType store_type,
CORBA_Environment *opt_ev)
{
xmlDocPtr parent_doc, prev_doc = NULL;
char *filename;
ConfigArchiver_ContainmentType contain_type;
ConfigArchiver_Location parent;
CORBA_Environment my_ev;
g_return_if_fail (location != CORBA_OBJECT_NIL);
g_return_if_fail (xml_doc != NULL);
if (opt_ev == NULL) {
opt_ev = &my_ev;
CORBA_exception_init (opt_ev);
}
contain_type = ConfigArchiver_Location_contains (location, backend_id, opt_ev);
parent = ConfigArchiver_Location__get_parent (location, opt_ev);
if (contain_type == ConfigArchiver_CONTAIN_NONE) {
if (parent == CORBA_OBJECT_NIL) {
fprintf (stderr, "Could not find a location in the " \
"tree ancestry that stores this " \
"backend: %s.\n", backend_id);
} else {
location_client_store_xml (parent, backend_id, xml_doc, store_type, opt_ev);
bonobo_object_release_unref (parent, NULL);
}
if (opt_ev == &my_ev)
CORBA_exception_free (opt_ev);
return;
}
if (contain_type == ConfigArchiver_CONTAIN_PARTIAL && store_type != ConfigArchiver_STORE_FULL && parent != CORBA_OBJECT_NIL) {
g_assert (store_type == ConfigArchiver_STORE_MASK_PREVIOUS ||
store_type == ConfigArchiver_STORE_COMPARE_PARENT);
parent_doc = location_client_load_rollback_data
(parent, NULL, 0, backend_id, TRUE, opt_ev);
if (store_type == ConfigArchiver_STORE_MASK_PREVIOUS)
prev_doc = location_client_load_rollback_data (location, NULL, 0, backend_id, FALSE, opt_ev);
if (store_type == ConfigArchiver_STORE_COMPARE_PARENT) {
subtract_xml_doc (xml_doc, parent_doc, FALSE);
} else {
subtract_xml_doc (parent_doc, prev_doc, FALSE);
subtract_xml_doc (xml_doc, parent_doc, TRUE);
}
xmlFreeDoc (parent_doc);
if (prev_doc != NULL)
xmlFreeDoc (prev_doc);
}
if (parent != CORBA_OBJECT_NIL)
bonobo_object_release_unref (parent, NULL);
filename = ConfigArchiver_Location_getStorageFilename (location, backend_id, store_type == ConfigArchiver_STORE_DEFAULT, opt_ev);
xmlSaveFile (filename, xml_doc);
CORBA_free (filename);
if (opt_ev == &my_ev)
CORBA_exception_free (opt_ev);
}
static void
merge_xml_docs (xmlDocPtr child_doc, xmlDocPtr parent_doc)
{
merge_xml_nodes (xmlDocGetRootElement (child_doc),
xmlDocGetRootElement (parent_doc));
}
static void
subtract_xml_doc (xmlDocPtr child_doc, xmlDocPtr parent_doc, gboolean strict)
{
subtract_xml_node (xmlDocGetRootElement (child_doc),
xmlDocGetRootElement (parent_doc), strict);
}
/* Merge contents of node1 and node2, where node1 overrides node2 as
* appropriate
*
* Notes: Two XML nodes are considered to be "the same" iff their names and
* all names and values of their attributes are the same. If that is not the
* case, they are considered "different" and will both be present in the
* merged node. If nodes are "the same", then this algorithm is called
* recursively. If nodes are CDATA, then node1 overrides node2 and the
* resulting node is just node1. The node merging is order-independent; child
* node from one tree are compared with all child nodes of the other tree
* regardless of the order they appear in. Hence one may have documents with
* different node orderings and the algorithm should still run correctly. It
* will not, however, run correctly in cases when the agent using this
* facility depends on the nodes being in a particular order.
*
* This XML node merging/comparison facility requires that the following
* standard be set for DTDs:
*
* Attributes' sole purpose is to identify a node. For example, a network
* configuration DTD might have an element like <interface name="eth0"> with a
* bunch of child nodes to configure that interface. The attribute "name" does
* not specify the configuration for the interface. It differentiates the node
* from the configuration for, say, interface eth1. Conversely, a node must be
* completely identified by its attributes. One cannot include identification
* information in the node's children, since otherwise the merging and
* subtraction algorithms will not know what to look for.
*
* As a corollary to the above, all configuration information must ultimately
* be in text nodes. For example, a text string might be stored as
* <configuration-item>my-value</configuration-item> but never as
* <configuration-item value="my-value"/>. As an example, if the latter is
* used, a child location might override a parent's setting for
* configuration-item. This algorithm will interpret those as different nodes
* and include them both in the merged result, since it will not have any way
* of knowing that they are really the same node with different
* configuration.
*/
static void
merge_xml_nodes (xmlNodePtr node1, xmlNodePtr node2)
{
xmlNodePtr child, tmp, iref;
GList *node1_children = NULL, *i;
gboolean found;
if (node1->type == XML_TEXT_NODE)
return;
for (child = node1->childs; child != NULL; child = child->next)
node1_children = g_list_prepend (node1_children, child);
node1_children = g_list_reverse (node1_children);
child = node2->childs;
while (child != NULL) {
tmp = child->next;
i = node1_children; found = FALSE;
while (i != NULL) {
iref = (xmlNodePtr) i->data;
if (compare_xml_nodes (iref, child)) {
merge_xml_nodes (iref, child);
if (i == node1_children)
node1_children = node1_children->next;
g_list_remove_link (node1_children, i);
g_list_free_1 (i);
found = TRUE;
break;
} else {
i = i->next;
}
}
if (found == FALSE) {
xmlUnlinkNode (child);
xmlAddChild (node1, child);
}
child = tmp;
}
g_list_free (node1_children);
}
/* Modifies node1 so that it only contains the parts different from node2;
* returns the modified node or NULL if the node should be destroyed
*
* strict determines whether the settings themselves are compared; it should
* be set to FALSE when the trees are being compared for the purpose of
* seeing what settings should be included in a tree and TRUE when one wants
* to restrict the settings included in a tree to those that have already been
* specified
*/
static xmlNodePtr
subtract_xml_node (xmlNodePtr node1, xmlNodePtr node2, gboolean strict)
{
xmlNodePtr child, tmp, iref;
GList *node2_children = NULL, *i;
gboolean found, same, all_same = TRUE;
if (node1->type == XML_TEXT_NODE) {
if (node2->type == XML_TEXT_NODE &&
(strict || !strcmp (xmlNodeGetContent (node1),
xmlNodeGetContent (node2))))
return NULL;
else
return node1;
}
if (node1->childs == NULL && node2->childs == NULL)
return NULL;
for (child = node2->childs; child != NULL; child = child->next)
node2_children = g_list_prepend (node2_children, child);
node2_children = g_list_reverse (node2_children);
child = node1->childs;
while (child != NULL) {
tmp = child->next;
i = node2_children; found = FALSE; all_same = TRUE;
while (i != NULL) {
iref = (xmlNodePtr) i->data;
if (compare_xml_nodes (child, iref)) {
same = (subtract_xml_node
(child, iref, strict) == NULL);
all_same = all_same && same;
if (same) {
xmlUnlinkNode (child);
xmlFreeNode (child);
}
if (i == node2_children)
node2_children = node2_children->next;
g_list_remove_link (node2_children, i);
g_list_free_1 (i);
found = TRUE;
break;
} else {
i = i->next;
}
}
if (!found)
all_same = FALSE;
child = tmp;
}
g_list_free (node2_children);
if (all_same)
return NULL;
else
return node1;
}
/* Return TRUE iff node1 and node2 are "the same" in the sense defined above */
static gboolean
compare_xml_nodes (xmlNodePtr node1, xmlNodePtr node2)
{
xmlAttrPtr attr;
gint count = 0;
if (strcmp (node1->name, node2->name))
return FALSE;
/* FIXME: This is worst case O(n^2), which can add up. Could we
* optimize for the case where people have attributes in the same
* order, or does not not matter? It probably does not matter, though,
* since people don't generally have more than one or two attributes
* in a tag anyway.
*/
for (attr = node1->properties; attr != NULL; attr = attr->next) {
g_assert (xmlNodeIsText (attr->val));
if (strcmp (xmlNodeGetContent (attr->val),
xmlGetProp (node2, attr->name)))
return FALSE;
count++;
}
/* FIXME: Is checking if the two nodes have the same number of
* attributes the correct policy here? Should we instead merge the
* attribute(s) that node1 is missing?
*/
for (attr = node2->properties; attr != NULL; attr = attr->next)
count--;
if (count == 0)
return TRUE;
else
return FALSE;
}

View file

@ -0,0 +1,46 @@
/* -*- mode: c; style: linux -*- */
/* archiver-client.h
* Copyright (C) 2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* 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 __ARCHIVER_CLIENT_H
#define __ARCHIVER_CLIENT_H
#include <gnome.h>
#include <libxml/tree.h>
#include <time.h>
#include "ConfigArchiver.h"
xmlDocPtr location_client_load_rollback_data (ConfigArchiver_Location location,
struct tm *date,
guint steps,
gchar *backend_id,
gboolean parent_chain,
CORBA_Environment *opt_ev);
void location_client_store_xml (ConfigArchiver_Location location,
gchar *backend_id,
xmlDocPtr xml_doc,
ConfigArchiver_StoreType store_type,
CORBA_Environment *opt_ev);
#endif /* __ARCHIVER_CLIENT_H */

View file

@ -42,7 +42,9 @@ struct _BackendListPrivate
GList *backend_ids;
};
static GtkObjectClass *parent_class;
#define BACKEND_LIST_FROM_SERVANT(servant) (BACKEND_LIST (bonobo_object_from_servant (servant)))
static BonoboXObjectClass *parent_class;
static void backend_list_init (BackendList *backend_list);
static void backend_list_class_init (BackendListClass *class);
@ -59,30 +61,64 @@ static void backend_list_finalize (GtkObject *object);
static void do_load (BackendList *backend_list);
static void do_save (BackendList *backend_list);
guint
backend_list_get_type (void)
/* CORBA interface methods */
static CORBA_boolean
impl_ConfigArchiver_BackendList_contains (PortableServer_Servant servant,
const CORBA_char *backend_id,
CORBA_Environment *ev)
{
static guint backend_list_type = 0;
if (!backend_list_type) {
GtkTypeInfo backend_list_info = {
"BackendList",
sizeof (BackendList),
sizeof (BackendListClass),
(GtkClassInitFunc) backend_list_class_init,
(GtkObjectInitFunc) backend_list_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
backend_list_type =
gtk_type_unique (gtk_object_get_type (),
&backend_list_info);
}
return backend_list_type;
return backend_list_contains (BACKEND_LIST_FROM_SERVANT (servant), backend_id);
}
static void
impl_ConfigArchiver_BackendList_add (PortableServer_Servant servant,
const CORBA_char *backend_id,
CORBA_Environment *ev)
{
backend_list_add (BACKEND_LIST_FROM_SERVANT (servant), backend_id);
}
static void
impl_ConfigArchiver_BackendList_remove (PortableServer_Servant servant,
const CORBA_char *backend_id,
CORBA_Environment *ev)
{
backend_list_remove (BACKEND_LIST_FROM_SERVANT (servant), backend_id);
}
static void
impl_ConfigArchiver_BackendList_save (PortableServer_Servant servant,
CORBA_Environment *ev)
{
backend_list_save (BACKEND_LIST_FROM_SERVANT (servant));
}
static ConfigArchiver_StringSeq *
impl_ConfigArchiver_BackendList__get_backends (PortableServer_Servant servant,
CORBA_Environment *ev)
{
ConfigArchiver_StringSeq *seq;
BackendList *backend_list = BACKEND_LIST_FROM_SERVANT (servant);
guint i = 0;
GList *node;
g_return_val_if_fail (backend_list != NULL, NULL);
g_return_val_if_fail (IS_BACKEND_LIST (backend_list), NULL);
seq = ConfigArchiver_StringSeq__alloc ();
seq->_length = g_list_length (backend_list->p->backend_ids);
seq->_buffer = CORBA_sequence_CORBA_string_allocbuf (seq->_length);
CORBA_sequence_set_release (seq, TRUE);
for (node = backend_list->p->backend_ids; node != NULL; node = node->next)
seq->_buffer[i++] = CORBA_string_dup (node->data);
return seq;
}
BONOBO_X_TYPE_FUNC_FULL (BackendList, ConfigArchiver_BackendList, BONOBO_X_OBJECT_TYPE, backend_list);
static void
backend_list_init (BackendList *backend_list)
{
@ -104,8 +140,15 @@ backend_list_class_init (BackendListClass *class)
object_class->set_arg = backend_list_set_arg;
object_class->get_arg = backend_list_get_arg;
parent_class = GTK_OBJECT_CLASS
(gtk_type_class (gtk_object_get_type ()));
class->epv.contains = impl_ConfigArchiver_BackendList_contains;
class->epv.add = impl_ConfigArchiver_BackendList_add;
class->epv.remove = impl_ConfigArchiver_BackendList_remove;
class->epv.save = impl_ConfigArchiver_BackendList_save;
class->epv._get_backends = impl_ConfigArchiver_BackendList__get_backends;
parent_class = BONOBO_X_OBJECT_CLASS
(gtk_type_class (BONOBO_X_OBJECT_TYPE));
}
static void
@ -173,16 +216,17 @@ backend_list_finalize (GtkObject *object)
GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
GtkObject *
BonoboObject *
backend_list_new (gboolean is_global)
{
return gtk_object_new (backend_list_get_type (),
"is-global", is_global,
NULL);
return BONOBO_OBJECT
(gtk_object_new (backend_list_get_type (),
"is-global", is_global,
NULL));
}
gboolean
backend_list_contains (BackendList *backend_list, gchar *backend_id)
backend_list_contains (BackendList *backend_list, const gchar *backend_id)
{
GList *node;
@ -226,25 +270,33 @@ backend_list_foreach (BackendList *backend_list, BackendCB callback,
}
void
backend_list_add (BackendList *backend_list, gchar *backend_id)
backend_list_add (BackendList *backend_list, const gchar *backend_id)
{
g_return_if_fail (backend_list != NULL);
g_return_if_fail (IS_BACKEND_LIST (backend_list));
g_return_if_fail (backend_id != NULL);
backend_list->p->backend_ids =
g_list_prepend (backend_list->p->backend_ids, backend_id);
g_list_prepend (backend_list->p->backend_ids, g_strdup (backend_id));
}
void
backend_list_remove (BackendList *backend_list, gchar *backend_id)
backend_list_remove (BackendList *backend_list, const gchar *backend_id)
{
gchar *tmp;
GList *node;
g_return_if_fail (backend_list != NULL);
g_return_if_fail (IS_BACKEND_LIST (backend_list));
g_return_if_fail (backend_id != NULL);
tmp = g_strdup (backend_id);
node = g_list_find (backend_list->p->backend_ids, tmp);
backend_list->p->backend_ids =
g_list_remove (backend_list->p->backend_ids, backend_id);
g_list_remove_link (backend_list->p->backend_ids, node);
g_free (node->data);
g_free (tmp);
g_list_free_1 (node);
}
void

View file

@ -25,6 +25,9 @@
#define __BACKEND_LIST_H
#include <gnome.h>
#include <bonobo.h>
#include "ConfigArchiver.h"
BEGIN_GNOME_DECLS
@ -40,33 +43,35 @@ typedef gint (*BackendCB) (BackendList *, gchar *, gpointer);
struct _BackendList
{
GtkObject parent;
BonoboXObject parent;
BackendListPrivate *p;
};
struct _BackendListClass
{
GtkObjectClass gtk_object_class;
BonoboXObjectClass parent_class;
POA_ConfigArchiver_BackendList__epv epv;
};
guint backend_list_get_type (void);
guint backend_list_get_type (void);
GtkObject *backend_list_new (gboolean is_global);
BonoboObject *backend_list_new (gboolean is_global);
gboolean backend_list_contains (BackendList *backend_list,
gchar *backend_id);
gboolean backend_list_contains (BackendList *backend_list,
const gchar *backend_id);
gboolean backend_list_foreach (BackendList *backend_list,
BackendCB callback,
gpointer data);
gboolean backend_list_foreach (BackendList *backend_list,
BackendCB callback,
gpointer data);
void backend_list_add (BackendList *backend_list,
gchar *backend_id);
void backend_list_remove (BackendList *backend_list,
gchar *backend_id);
void backend_list_add (BackendList *backend_list,
const gchar *backend_id);
void backend_list_remove (BackendList *backend_list,
const gchar *backend_id);
void backend_list_save (BackendList *backend_list);
void backend_list_save (BackendList *backend_list);
END_GNOME_DECLS

View file

@ -223,8 +223,8 @@ real_sync (BonoboConfigDatabase *db,
if (!db->writeable)
return;
location_store_xml (archiver_db->location, archiver_db->backend_id,
archiver_db->doc, STORE_MASK_PREVIOUS);
location_client_store_xml (archiver_db->location, archiver_db->backend_id,
archiver_db->doc, ConfigArchiver_STORE_MASK_PREVIOUS, ev);
arg = bonobo_arg_new (BONOBO_ARG_NULL);
bonobo_event_source_notify_listeners (archiver_db->es, "Bonobo/ConfigDatabase:sync", arg, ev);
@ -470,29 +470,12 @@ pb_get_fn (BonoboPropertyBag *bag, BonoboArg *arg,
gpointer user_data)
{
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (user_data);
gint id;
ConfigLog *log;
struct tm *mod;
time_t val;
extern int daylight;
log = location_get_config_log (archiver_db->location);
id = config_log_get_rollback_id_by_steps (log, 0, archiver_db->real_name);
if (id < 0)
{
BONOBO_ARG_SET_GENERAL (arg, 0,
TC_ulonglong, CORBA_unsigned_long_long, NULL);
return;
}
val = ConfigArchiver_Location_getModificationTime
(archiver_db->location, archiver_db->backend_id, ev);
mod = config_log_get_date_for_id (log, id);
val = mktime (mod);
g_print ("%i\n", mod->tm_hour);
if (daylight)
val -= 3600;
BONOBO_ARG_SET_GENERAL (arg, val,
TC_ulonglong, CORBA_unsigned_long_long, NULL);
BONOBO_ARG_SET_GENERAL (arg, val, TC_ulonglong, CORBA_unsigned_long_long, NULL);
}
static void
@ -509,6 +492,8 @@ bonobo_config_archiver_destroy (GtkObject *object)
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (object);
CORBA_Environment ev;
DEBUG_MSG ("Enter");
CORBA_exception_init (&ev);
if (archiver_db->real_name != NULL) {
@ -518,16 +503,24 @@ bonobo_config_archiver_destroy (GtkObject *object)
CORBA_exception_free (&ev);
if (archiver_db->doc)
if (archiver_db->doc != NULL)
xmlFreeDoc (archiver_db->doc);
if (archiver_db->filename)
if (archiver_db->filename != NULL)
g_free (archiver_db->filename);
if (archiver_db->fp)
if (archiver_db->fp != NULL)
fclose (archiver_db->fp);
if (archiver_db->location != CORBA_OBJECT_NIL)
bonobo_object_release_unref (archiver_db->location, NULL);
if (archiver_db->archive != CORBA_OBJECT_NIL)
bonobo_object_release_unref (archiver_db->archive, NULL);
parent_class->destroy (object);
DEBUG_MSG ("Exit");
}
@ -632,60 +625,67 @@ fill_cache (BonoboConfigArchiver *archiver_db)
}
Bonobo_ConfigDatabase
bonobo_config_archiver_new (const char *backend_id, const char *location_id)
bonobo_config_archiver_new (Bonobo_Moniker parent,
const Bonobo_ResolveOptions *options,
const char *backend_id,
const char *location_id,
CORBA_Environment *ev)
{
BonoboConfigArchiver *archiver_db;
Bonobo_ConfigDatabase db;
CORBA_Environment ev;
gchar *real_name;
static Archive *archive = NULL;
g_return_val_if_fail (backend_id != NULL, NULL);
CORBA_exception_init (&ev);
DEBUG_MSG ("Enter");
if (location_id == NULL)
real_name = g_strdup (backend_id);
else
real_name = g_strconcat ("[", location_id, "]", backend_id, NULL);
db = bonobo_url_lookup ("BONOBO_CONF:ARCHIVER", real_name, &ev);
db = bonobo_url_lookup ("BONOBO_CONF:ARCHIVER", real_name, ev);
if (BONOBO_EX (&ev))
if (BONOBO_EX (ev)) {
db = CORBA_OBJECT_NIL;
CORBA_exception_free (&ev);
CORBA_exception_init (ev);
}
if (db) {
g_free (real_name);
return bonobo_object_dup_ref (db, NULL);
}
if (!(archiver_db = gtk_type_new (BONOBO_CONFIG_ARCHIVER_TYPE))) {
DEBUG_MSG ("Creating object");
if ((archiver_db = gtk_type_new (BONOBO_CONFIG_ARCHIVER_TYPE)) == NULL) {
g_free (real_name);
return CORBA_OBJECT_NIL;
}
if (archive == NULL)
archive = ARCHIVE (archive_load (FALSE));
archiver_db->archive = Bonobo_Moniker_resolve (parent, options, "IDL:ConfigArchiver/Archive:1.0", ev);
if (BONOBO_EX (ev) || archiver_db->archive == CORBA_OBJECT_NIL) {
g_critical ("Could not resolve parent moniker to an archive");
bonobo_object_unref (BONOBO_OBJECT (archiver_db));
return CORBA_OBJECT_NIL;
}
if (location_id == NULL || *location_id == '\0')
archiver_db->location = archive_get_current_location (archive);
archiver_db->location = ConfigArchiver_Archive__get_currentLocation (archiver_db->archive, ev);
else
archiver_db->location = archive_get_location (archive, location_id);
archiver_db->location = ConfigArchiver_Archive_getLocation (archiver_db->archive, location_id, ev);
if (archiver_db->location == NULL) {
if (archiver_db->location == CORBA_OBJECT_NIL) {
bonobo_object_unref (BONOBO_OBJECT (archiver_db));
return CORBA_OBJECT_NIL;
}
archiver_db->backend_id = g_strdup (backend_id);
archiver_db->archive = archive;
archiver_db->real_name = real_name;
archiver_db->doc = location_load_rollback_data
(archiver_db->location, NULL, 0, archiver_db->backend_id, TRUE);
archiver_db->doc = location_client_load_rollback_data
(archiver_db->location, NULL, 0, archiver_db->backend_id, TRUE, ev);
if (archiver_db->doc == NULL) {
gchar *filename;
@ -736,7 +736,9 @@ bonobo_config_archiver_new (const char *backend_id, const char *location_id)
db = CORBA_Object_duplicate (BONOBO_OBJREF (archiver_db), NULL);
bonobo_url_register ("BONOBO_CONF:ARCHIVER", real_name, NULL, db, &ev);
bonobo_url_register ("BONOBO_CONF:ARCHIVER", real_name, NULL, db, ev);
DEBUG_MSG ("Exit: %p", db);
return db;
}

View file

@ -18,8 +18,7 @@
#include <bonobo/bonobo-event-source.h>
#include <bonobo/bonobo-property-bag.h>
#include "archive.h"
#include "location.h"
#include "archiver-client.h"
BEGIN_GNOME_DECLS
@ -49,21 +48,21 @@ typedef struct {
typedef struct _BonoboConfigArchiver BonoboConfigArchiver;
struct _BonoboConfigArchiver {
BonoboConfigDatabase base;
char *filename;
FILE *fp;
xmlDocPtr doc;
DirData *dir;
guint time_id;
BonoboConfigDatabase base;
Archive *archive;
Location *location;
gchar *backend_id;
gchar *real_name;
char *filename;
FILE *fp;
xmlDocPtr doc;
DirData *dir;
guint time_id;
BonoboEventSource *es;
BonoboPropertyBag *pb;
ConfigArchiver_Archive archive;
ConfigArchiver_Location location;
gchar *backend_id;
gchar *real_name;
BonoboEventSource *es;
BonoboPropertyBag *pb;
};
typedef struct {
@ -75,7 +74,11 @@ GtkType
bonobo_config_archiver_get_type (void);
Bonobo_ConfigDatabase
bonobo_config_archiver_new (const char *backend_id, const char *location_id);
bonobo_config_archiver_new (Bonobo_Moniker parent,
const Bonobo_ResolveOptions *options,
const char *backend_id,
const char *location_id,
CORBA_Environment *ev);
END_GNOME_DECLS

View file

@ -17,9 +17,14 @@
#include <bonobo/bonobo-exception.h>
#include "bonobo-config-archiver.h"
#include "archive.h"
#include "util.h"
#define EX_SET_NOT_FOUND(ev) bonobo_exception_set (ev, ex_Bonobo_Moniker_InterfaceNotFound)
static Archive *user_archive = NULL;
static Archive *global_archive = NULL;
/* parse_name
*
* Given a moniker with a backend id and (possibly) a location id encoded
@ -52,16 +57,85 @@ parse_name (const gchar *name, gchar **backend_id, gchar **location)
return TRUE;
}
static Bonobo_Unknown
archiver_resolve (BonoboMoniker *moniker,
const Bonobo_ResolveOptions *options,
const CORBA_char *requested_interface,
CORBA_Environment *ev)
static void
archive_destroy_cb (Archive *archive)
{
Bonobo_Moniker parent;
Bonobo_ConfigDatabase db, pdb = CORBA_OBJECT_NIL;
const gchar *name;
gchar *backend_id, *location;
if (archive == global_archive)
global_archive = NULL;
else if (archive == user_archive)
user_archive = NULL;
}
static Bonobo_Unknown
archive_resolve (BonoboMoniker *moniker,
const Bonobo_ResolveOptions *options,
const CORBA_char *requested_interface,
CORBA_Environment *ev)
{
const gchar *name;
Bonobo_Unknown ret;
DEBUG_MSG ("Enter");
if (strcmp (requested_interface, "IDL:ConfigArchiver/Archive:1.0")) {
EX_SET_NOT_FOUND (ev);
return CORBA_OBJECT_NIL;
}
name = bonobo_moniker_get_name (moniker);
if (!strcmp (name, "global-archive")) {
DEBUG_MSG ("Global archive requested");
if (global_archive == NULL) {
global_archive = ARCHIVE (archive_load (TRUE));
gtk_signal_connect (GTK_OBJECT (global_archive), "destroy", GTK_SIGNAL_FUNC (archive_destroy_cb), NULL);
ret = CORBA_Object_duplicate (BONOBO_OBJREF (global_archive), ev);
} else {
ret = bonobo_object_dup_ref (BONOBO_OBJREF (global_archive), ev);
}
if (BONOBO_EX (ev)) {
g_critical ("Cannot duplicate object");
bonobo_object_release_unref (ret, NULL);
ret = CORBA_OBJECT_NIL;
}
}
else if (!strcmp (name, "user-archive")) {
if (user_archive == NULL) {
user_archive = ARCHIVE (archive_load (FALSE));
gtk_signal_connect (GTK_OBJECT (user_archive), "destroy", GTK_SIGNAL_FUNC (archive_destroy_cb), NULL);
ret = CORBA_Object_duplicate (BONOBO_OBJREF (user_archive), ev);
} else {
ret = bonobo_object_dup_ref (BONOBO_OBJREF (user_archive), ev);
}
if (BONOBO_EX (ev)) {
g_critical ("Cannot duplicate object");
bonobo_object_release_unref (ret, NULL);
ret = CORBA_OBJECT_NIL;
}
} else {
EX_SET_NOT_FOUND (ev);
ret = CORBA_OBJECT_NIL;
}
DEBUG_MSG ("Exit");
return ret;
}
static Bonobo_Unknown
archiverdb_resolve (BonoboMoniker *moniker,
const Bonobo_ResolveOptions *options,
const CORBA_char *requested_interface,
CORBA_Environment *ev)
{
Bonobo_Moniker parent;
Bonobo_ConfigDatabase db;
const gchar *name;
gchar *backend_id, *locid;
if (strcmp (requested_interface, "IDL:Bonobo/ConfigDatabase:1.0")) {
EX_SET_NOT_FOUND (ev);
@ -72,42 +146,27 @@ archiver_resolve (BonoboMoniker *moniker,
if (BONOBO_EX (ev))
return CORBA_OBJECT_NIL;
name = bonobo_moniker_get_name (moniker);
if (parent != CORBA_OBJECT_NIL) {
pdb = Bonobo_Moniker_resolve (parent, options,
"IDL:Bonobo/ConfigDatabase:1.0", ev);
bonobo_object_release_unref (parent, NULL);
if (BONOBO_EX (ev) || pdb == CORBA_OBJECT_NIL)
return CORBA_OBJECT_NIL;
}
if (parse_name (name, &backend_id, &location) < 0) {
if (parent == CORBA_OBJECT_NIL) {
EX_SET_NOT_FOUND (ev);
return CORBA_OBJECT_NIL;
}
if (!(db = bonobo_config_archiver_new (backend_id, location))) {
g_free (backend_id);
g_free (location);
name = bonobo_moniker_get_name (moniker);
if (parse_name (name, &backend_id, &locid) < 0) {
EX_SET_NOT_FOUND (ev);
return CORBA_OBJECT_NIL;
return CORBA_OBJECT_NIL;
}
db = bonobo_config_archiver_new (parent, options, backend_id, locid, ev);
bonobo_object_release_unref (parent, NULL);
if (db == CORBA_OBJECT_NIL || BONOBO_EX (ev))
EX_SET_NOT_FOUND (ev);
g_free (backend_id);
g_free (location);
if (pdb != CORBA_OBJECT_NIL) {
Bonobo_ConfigDatabase_addDatabase (db, pdb, "", Bonobo_ConfigDatabase_DEFAULT, ev);
if (BONOBO_EX (ev)) {
bonobo_object_release_unref (pdb, NULL);
bonobo_object_release_unref (db, NULL);
return CORBA_OBJECT_NIL;
}
}
g_free (locid);
return db;
}
@ -118,13 +177,16 @@ bonobo_moniker_archiver_factory (BonoboGenericFactory *this,
const char *object_id,
void *closure)
{
if (!strcmp (object_id, "OAFIID:Bonobo_Moniker_archiver")) {
return BONOBO_OBJECT (bonobo_moniker_simple_new (
"archiver:", archiver_resolve));
} else
if (!strcmp (object_id, "OAFIID:Bonobo_Moniker_archiverdb")) {
return BONOBO_OBJECT (bonobo_moniker_simple_new
("archiverdb:", archiverdb_resolve));
}
else if (!strcmp (object_id, "OAFIID:Bonobo_Moniker_archive")) {
return BONOBO_OBJECT (bonobo_moniker_simple_new
("archive:", archive_resolve));
} else {
g_warning ("Failing to manufacture a '%s'", object_id);
}
return NULL;
}

438
archiver/config-archiver.c Normal file
View file

@ -0,0 +1,438 @@
/* -*- mode: c; style: linux -*- */
/* main.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* 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 <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/file.h>
#include <unistd.h>
#include <errno.h>
#include <gnome.h>
#include <bonobo.h>
#include <gnome-xml/parser.h>
#include "archiver-client.h"
#include "util.h"
/* Variables resulting from command line parsing */
static gboolean store;
static gboolean rollback;
static gboolean change_location;
static gboolean rename_location;
static gboolean push_config;
static gboolean garbage_collect;
static gboolean add_location;
static gboolean remove_location;
static gboolean add_backend;
static gboolean remove_backend;
static gboolean global;
static const gchar *location_id;
static gchar *backend_id;
static gboolean compare_parent;
static gboolean mask_previous;
static gchar *date_str;
static gboolean all;
static gchar *revision_id;
static gboolean last;
static guint steps;
static gboolean show;
static gchar *parent_str;
static gchar *new_name;
static gboolean contain_full;
static gboolean contain_partial;
static gboolean master;
static struct poptOption archiver_operations[] = {
{"store", 's', POPT_ARG_NONE, &store, 0,
N_("Store XML data in the archive")},
{"rollback", 'r', POPT_ARG_NONE, &rollback, 0,
N_("Roll back the configuration to a given point")},
{"change-location", 'c', POPT_ARG_NONE, &change_location, 0,
N_("Change the location profile to the given one")},
{"push-config", 'p', POPT_ARG_NONE, &push_config, 0,
N_("Push configuration data out to client machines (UNIMPLEMENTED)")},
{"rename-location", '\0', POPT_ARG_NONE, &rename_location, 0,
N_("Rename a location to a new name")},
{"add-location", '\0', POPT_ARG_NONE, &add_location, 0,
N_("Add a new location to the archive")},
{"remove-location", '\0', POPT_ARG_NONE, &remove_location, 0,
N_("Remove a location from the archive")},
{"add-backend", '\0', POPT_ARG_NONE, &add_backend, 0,
N_("Add a given backend to the given location")},
{"remove-backend", '\0', POPT_ARG_NONE, &remove_backend, 0,
N_("Remove the given backend from the given location")},
{"garbage-collect", '\0', POPT_ARG_NONE, &garbage_collect, 0,
N_("Perform garbage collection on the given location")},
{NULL, '\0', 0, NULL, 0}
};
static struct poptOption global_options[] = {
{"global", 'g', POPT_ARG_NONE, &global, 0,
N_("Use the global repository")},
{"location", 'l', POPT_ARG_STRING, &location_id, 0,
N_("Identifier of location profile on which to operate"),
N_("LOCATION")},
{"backend", 'b', POPT_ARG_STRING, &backend_id, 0,
N_("Backend being used for this operation"), N_("BACKEND_ID")},
{NULL, '\0', 0, NULL, 0}
};
static struct poptOption store_options[] = {
{"compare-parent", '\0', POPT_ARG_NONE, &compare_parent, 0,
N_("Store only the differences with the parent location's config")},
{"mask-previous", '\0', POPT_ARG_NONE, &mask_previous, 0,
N_("Store only those settings set in the previous config")},
{NULL, '\0', 0, NULL, 0}
};
static struct poptOption rollback_options[] = {
{"date", 'd', POPT_ARG_STRING, &date_str, 0,
N_("Date to which to roll back"), N_("DATE")},
{"all", 'a', POPT_ARG_NONE, &all, 0,
N_("Roll back all configuration items")},
{"revision-id", 'i', POPT_ARG_INT, &revision_id, 0,
N_("Roll back to the revision REVISION_ID"), N_("REVISION_ID")},
{"last", 't', POPT_ARG_NONE, &last, 0,
N_("Roll back to the last known revision")},
{"steps", '\0', POPT_ARG_INT, &steps, 0,
N_("Roll back by STEPS revisions"), N_("STEPS")},
{"show", 'h', POPT_ARG_NONE, &show, 0,
N_("Don't run the backend, just dump the output")},
{NULL, '\0', 0, NULL, 0}
};
static struct poptOption add_rename_location_options[] = {
{"parent", '\0', POPT_ARG_STRING, &parent_str, 0,
N_("Parent location for the new location"), N_("PARENT")},
{"new-name", '\0', POPT_ARG_STRING, &new_name, 0,
N_("New name to assign to the location"), N_("NEW_NAME")},
{NULL, '\0', 0, NULL, 0}
};
static struct poptOption add_remove_backend_options[] = {
{"master", '\0', POPT_ARG_NONE, &master, 0,
N_("Add/remove this backend to/from the master backend list")},
{"full", '\0', POPT_ARG_NONE, &contain_full, 0,
N_("Full containment")},
{"partial", '\0', POPT_ARG_NONE, &contain_partial, 0,
N_("Partial containment")},
{NULL, '\0', 0, NULL, 0}
};
static xmlDocPtr
xml_load_from_stream (FILE *stream)
{
GString *str;
gchar buffer[4097];
xmlDocPtr doc;
size_t t;
str = g_string_new ("");
while (!feof (stream)) {
t = fread (buffer, sizeof (char), 4096, stream);
buffer[t] = '\0';
g_string_append (str, buffer);
}
doc = xmlParseDoc (str->str);
g_string_free (str, TRUE);
return doc;
}
static ConfigArchiver_StringSeq *
make_backend_id_seq (gchar *backend_id, ...)
{
ConfigArchiver_StringSeq *seq;
seq = ConfigArchiver_StringSeq__alloc ();
seq->_length = 1;
seq->_buffer = CORBA_sequence_CORBA_string_allocbuf (1);
seq->_buffer[0] = CORBA_string_dup (backend_id);
return seq;
}
static void
do_store (ConfigArchiver_Location location, CORBA_Environment *ev)
{
ConfigArchiver_StoreType type;
xmlDocPtr doc;
if (!backend_id) {
fprintf (stderr, "No backend specified\n");
return;
}
if (mask_previous)
type = ConfigArchiver_STORE_MASK_PREVIOUS;
else if (compare_parent)
type = ConfigArchiver_STORE_COMPARE_PARENT;
else
type = ConfigArchiver_STORE_FULL;
doc = xml_load_from_stream (stdin);
location_client_store_xml (location, backend_id, doc, type, ev);
}
static void
do_rollback (ConfigArchiver_Location location, CORBA_Environment *ev)
{
struct tm *date = NULL;
ConfigArchiver_StringSeq *seq;
ConfigArchiver_Time tm;
xmlDocPtr doc;
if (date_str)
date = parse_date (date_str);
else if (last || steps > 0)
date = NULL;
else if (!revision_id) {
fprintf (stderr, "No date specified\n");
return;
}
if (backend_id != NULL && (date != NULL || last)) {
/* FIXME: Need to support specifying multiple backends */
if (show) {
doc = location_client_load_rollback_data (location, date, 0, backend_id, TRUE, ev);
xmlDocDump (stdout, doc);
xmlFreeDoc (doc);
} else {
tm = mktime (date);
seq = make_backend_id_seq (backend_id, NULL);
ConfigArchiver_Location_rollbackBackends (location, tm, 0, seq, TRUE, ev);
CORBA_free (seq);
}
}
else if (backend_id != NULL && steps != 0) {
if (show) {
doc = location_client_load_rollback_data (location, date, steps, backend_id, TRUE, ev);
xmlDocDump (stdout, doc);
xmlFreeDoc (doc);
} else {
seq = make_backend_id_seq (backend_id, NULL);
ConfigArchiver_Location_rollbackBackends (location, 0, steps, seq, TRUE, ev);
CORBA_free (seq);
}
} else {
g_message ("No backend specified\n");
return;
}
}
static void
do_change_location (ConfigArchiver_Archive archive, ConfigArchiver_Location location, CORBA_Environment *ev)
{
ConfigArchiver_Archive__set_currentLocation (archive, location, ev);
}
static void
do_rename_location (ConfigArchiver_Archive archive, ConfigArchiver_Location location, CORBA_Environment *ev)
{
gboolean is_current;
CORBA_char *locid, *cid;
if (new_name == NULL) {
fprintf (stderr, "You did not specify a new name. Try --help\n");
} else {
locid = ConfigArchiver_Location__get_id (location, ev);
cid = ConfigArchiver_Archive__get_currentLocationId (archive, ev);
if (!strcmp (locid, cid))
is_current = TRUE;
else
is_current = FALSE;
CORBA_free (locid);
CORBA_free (cid);
ConfigArchiver_Location__set_id (location, new_name, ev);
if (is_current)
ConfigArchiver_Archive__set_currentLocationId (archive, new_name, ev);
}
}
static void
do_add_location (ConfigArchiver_Archive archive, CORBA_Environment *ev)
{
ConfigArchiver_Location parent_location = CORBA_OBJECT_NIL;
if (location_id == NULL) {
fprintf (stderr, "Error: You did not specify a location name\n");
return;
}
if (parent_str != NULL) {
parent_location = ConfigArchiver_Archive_getLocation (archive, parent_str, ev);
if (parent_location == NULL && !strcmp (parent_str, "default"))
parent_location =
ConfigArchiver_Archive_createLocation (archive, "default", _("Default Location"),
CORBA_OBJECT_NIL, ev);
}
ConfigArchiver_Archive_createLocation (archive, location_id, location_id, parent_location, ev);
}
static void
do_remove_location (ConfigArchiver_Location location, CORBA_Environment *ev)
{
ConfigArchiver_Location_delete (location, ev);
}
static void
do_add_backend (ConfigArchiver_Location location, CORBA_Environment *ev)
{
ConfigArchiver_ContainmentType type;
if (contain_full && contain_partial) {
fprintf (stderr, "Error: Cannot have both full and partial "
"containment\n");
return;
}
else if (contain_partial) {
type = ConfigArchiver_CONTAIN_PARTIAL;
} else {
type = ConfigArchiver_CONTAIN_FULL;
}
ConfigArchiver_Location_addBackend (location, backend_id, type, ev);
}
static void
do_remove_backend (ConfigArchiver_Location location, CORBA_Environment *ev)
{
ConfigArchiver_Location_removeBackend (location, backend_id, ev);
}
static void
do_garbage_collect (ConfigArchiver_Location location, CORBA_Environment *ev)
{
ConfigArchiver_Location_garbageCollect (location, ev);
}
int
main (int argc, char **argv)
{
CORBA_ORB orb;
ConfigArchiver_Archive archive;
ConfigArchiver_Location location = CORBA_OBJECT_NIL;
CORBA_Environment ev;
/* For Electric Fence */
free (malloc (1));
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
textdomain (PACKAGE);
CORBA_exception_init (&ev);
gnomelib_register_popt_table (global_options,
_("Global archiver options"));
gnomelib_register_popt_table (archiver_operations,
_("Archiver commands"));
gnomelib_register_popt_table (store_options,
_("Options for storing data"));
gnomelib_register_popt_table (rollback_options,
_("Options for rolling back"));
gnomelib_register_popt_table (add_rename_location_options,
_("Options for adding or renaming " \
"locations"));
gnomelib_register_popt_table (add_remove_backend_options,
_("Options for adding and removing " \
"backends"));
gtk_type_init ();
gnomelib_init ("archiver", VERSION);
gnomelib_parse_args (argc, argv, 0);
orb = oaf_init (argc, argv);
if (bonobo_init (orb, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL) == FALSE)
g_error ("Cannot initialize Bonobo");
if (global)
archive = bonobo_get_object ("archive:global-archive", "IDL:ConfigArchiver/Archive:1.0", &ev);
else
archive = bonobo_get_object ("archive:user-archive", "IDL:ConfigArchiver/Archive:1.0", &ev);
if (archive == CORBA_OBJECT_NIL) {
g_critical ("Could not open archive\n");
return -1;
}
if (!add_location) {
if (location_id == NULL)
location_id = ConfigArchiver_Archive__get_currentLocationId (archive, &ev);
location = ConfigArchiver_Archive_getLocation (archive, location_id, &ev);
if (location == CORBA_OBJECT_NIL) {
g_critical ("Error: Could not open location %s\n", location_id);
return -1;
}
}
if (store)
do_store (location, &ev);
else if (rollback)
do_rollback (location, &ev);
else if (change_location)
do_change_location (archive, location, &ev);
else if (rename_location)
do_rename_location (archive, location, &ev);
else if (add_location)
do_add_location (archive, &ev);
else if (remove_location)
do_remove_location (location, &ev);
else if (add_backend)
do_add_backend (location, &ev);
else if (remove_backend)
do_remove_backend (location, &ev);
else if (garbage_collect)
do_garbage_collect (location, &ev);
bonobo_object_release_unref (archive, NULL);
if (location != CORBA_OBJECT_NIL)
bonobo_object_release_unref (location, NULL);
return 0;
}

View file

@ -89,7 +89,7 @@ static GList *find_config_log_entry_date (ConfigLog *config_log,
struct tm *date);
static GList *find_config_log_entry_backend (ConfigLog *config_log,
GList *start,
gchar *backend_id);
const gchar *backend_id);
static GList *load_log_entry (ConfigLog *config_log,
GList *last);
@ -300,7 +300,7 @@ config_log_delete (ConfigLog *config_log)
gint
config_log_get_rollback_id_for_date (ConfigLog *config_log,
struct tm *date,
gchar *backend_id)
const gchar *backend_id)
{
GList *node;
@ -333,7 +333,8 @@ config_log_get_rollback_id_for_date (ConfigLog *config_log,
gint
config_log_get_rollback_id_by_steps (ConfigLog *config_log,
guint steps, gchar *backend_id)
guint steps,
const gchar *backend_id)
{
GList *node;
@ -394,7 +395,7 @@ config_log_get_backend_id_for_id (ConfigLog *config_log, gint id)
/* Return the date the data with the given id was written */
struct tm *
const struct tm *
config_log_get_date_for_id (ConfigLog *config_log, gint id)
{
GList *node;
@ -429,8 +430,9 @@ config_log_get_date_for_id (ConfigLog *config_log, gint id)
**/
gint
config_log_write_entry (ConfigLog *config_log, gchar *backend_id,
gboolean is_default_data)
config_log_write_entry (ConfigLog *config_log,
const gchar *backend_id,
gboolean is_default_data)
{
ConfigLogEntry *entry;
@ -454,9 +456,6 @@ config_log_write_entry (ConfigLog *config_log, gchar *backend_id,
g_list_prepend (config_log->p->log_data, entry);
dump_log (config_log);
if (config_log->p->file_stream != NULL)
fclose (config_log->p->file_stream);
do_load (config_log);
return entry->id;
}
@ -565,6 +564,7 @@ config_log_garbage_collect (ConfigLog *config_log,
GList *node, *list = NULL;
ConfigLogEntry *e1, *e2;
time_t t1, t2, now;
struct tm now_b, *tmp_date;
g_return_if_fail (config_log != NULL);
g_return_if_fail (IS_CONFIG_LOG (config_log));
@ -593,15 +593,27 @@ config_log_garbage_collect (ConfigLog *config_log,
if (list == NULL) return;
now = time (NULL);
gmtime_r (&now, &now_b);
now = mktime (&now_b);
for (node = list; node->next != NULL; node = node->next) {
e1 = ((GList *) node->data)->data;
e2 = ((GList *) node->next->data)->data;
t1 = mktime (e1->date);
t2 = mktime (e2->date);
tmp_date = dup_date (e1->date);
t1 = mktime (tmp_date);
g_free (tmp_date);
if (K_CONST * (t2 - t1) < now - t2) {
tmp_date = dup_date (e2->date);
t2 = mktime (tmp_date);
g_free (tmp_date);
if (now < t2 || now < t1)
g_warning ("Log entry is in the future!");
if (t1 > t2)
g_warning ("Log entries are out of order!");
if (K_CONST * difftime (t2, t1) < difftime (now, t2)) {
config_log->p->log_data =
g_list_remove_link (config_log->p->log_data, node->data);
callback (config_log, backend_id, e1->id, data);
@ -693,8 +705,9 @@ find_config_log_entry_date (ConfigLog *config_log, GList *start,
*/
static GList *
find_config_log_entry_backend (ConfigLog *config_log, GList *start,
gchar *backend_id)
find_config_log_entry_backend (ConfigLog *config_log,
GList *start,
const gchar *backend_id)
{
GList *last;
ConfigLogEntry *entry;
@ -812,6 +825,9 @@ parse_line (char *buffer, int *id, struct tm *date, char **backend_id)
if (extract_number (&buffer, &date->tm_sec, 2) == FALSE)
return FALSE;
date->tm_gmtoff = 0;
date->tm_zone = "GMT";
if (!isspace (*buffer) || *(buffer + 1) == '\0') return FALSE;
buffer++;
@ -918,10 +934,10 @@ static struct tm *
get_current_date (void)
{
time_t current_time;
struct tm *time_1, *ret;
struct tm time_2, *time_1 = &time_2, *ret;
current_time = time (NULL);
time_1 = localtime (&current_time);
gmtime_r (&current_time, time_1);
ret = g_new (struct tm, 1);
memcpy (ret, time_1, sizeof (struct tm));
return ret;
@ -952,7 +968,7 @@ dump_log (ConfigLog *config_log)
{
char *filename_out;
GList *first;
FILE *output;
FILE *input, *output;
DEBUG_MSG ("Enter");
@ -983,8 +999,9 @@ dump_log (ConfigLog *config_log)
((config_log->p->first_old == NULL && config_log->p->log_data == NULL) ||
(config_log->p->first_old != NULL && config_log->p->log_data != NULL)))
{
rewind (config_log->p->file_stream);
dump_file (config_log->p->file_stream, output);
input = fopen (config_log->p->filename, "r");
dump_file (input, output);
fclose (input);
}
config_log->p->first_old = config_log->p->log_data;

View file

@ -61,18 +61,18 @@ void config_log_delete (ConfigLog *config_log)
gint config_log_get_rollback_id_for_date (ConfigLog *config_log,
struct tm *date,
gchar *backend_id);
const gchar *backend_id);
gint config_log_get_rollback_id_by_steps (ConfigLog *config_log,
guint steps,
gchar *backend_id);
const gchar *backend_id);
gchar *config_log_get_backend_id_for_id (ConfigLog *config_log,
gint id);
struct tm *config_log_get_date_for_id (ConfigLog *config_log,
const struct tm *config_log_get_date_for_id (ConfigLog *config_log,
gint id);
gint config_log_write_entry (ConfigLog *config_log,
gchar *backend_id,
const gchar *backend_id,
gboolean is_default_data);
void config_log_iterate (ConfigLog *config_log,

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,9 @@
#include <gnome.h>
#include <tree.h>
#include <bonobo.h>
#include "ConfigArchiver.h"
#include "config-log.h"
@ -37,118 +40,100 @@ typedef struct _LocationClass LocationClass;
typedef struct _LocationPrivate LocationPrivate;
typedef struct _Archive Archive;
typedef enum _ContainmentType ContainmentType;
typedef enum _StoreType StoreType;
typedef ConfigArchiver_ContainmentType ContainmentType;
typedef ConfigArchiver_StoreType StoreType;
typedef int (*LocationBackendCB) (Location *, gchar *, gpointer);
struct _Location
{
GtkObject object;
BonoboXObject object;
LocationPrivate *p;
};
struct _LocationClass
{
GtkObjectClass parent;
BonoboXObjectClass parent;
POA_ConfigArchiver_Location__epv epv;
gboolean (*do_rollback) (Location *location,
gchar *backend_id,
xmlDocPtr xml_doc);
};
enum _ContainmentType
{
CONTAIN_NONE, CONTAIN_PARTIAL, CONTAIN_FULL
};
guint location_get_type (void);
enum _StoreType
{
STORE_DEFAULT, STORE_FULL, STORE_COMPARE_PARENT, STORE_MASK_PREVIOUS
};
BonoboObject *location_new (Archive *archive,
const gchar *locid,
const gchar *label,
Location *parent);
BonoboObject *location_open (Archive *archive,
const gchar *locid);
guint location_get_type (void);
void location_delete (Location *location);
GtkObject *location_new (Archive *archive,
const gchar *locid,
Location *inherits);
GtkObject *location_open (Archive *archive,
const gchar *locid);
gchar *location_get_storage_filename (Location *location,
const gchar *backend_id,
gboolean is_default);
gchar *location_get_rollback_filename (Location *location,
struct tm *date,
gint steps,
const gchar *backend_id,
gboolean parent_chain);
void location_close (Location *location);
void location_delete (Location *location);
gint location_store (Location *location,
gchar *backend_id,
FILE *input,
ConfigArchiver_StoreType store_type);
void location_store_xml (Location *location,
gchar *backend_id,
xmlDocPtr xml_doc,
ConfigArchiver_StoreType store_type);
gint location_store (Location *location,
gchar *backend_id,
FILE *input,
StoreType store_type);
void location_store_xml (Location *location,
gchar *backend_id,
xmlDocPtr xml_doc,
StoreType store_type);
void location_rollback_backends_to (Location *location,
struct tm *date,
gint steps,
GList *backends,
gboolean parent_chain);
void location_rollback_backend_to (Location *location,
struct tm *date,
gchar *backend_id,
gboolean parent_chain);
void location_rollback_backends_to (Location *location,
struct tm *date,
GList *backends,
gboolean parent_chain);
void location_rollback_all_to (Location *location,
struct tm *date,
gboolean parent_chain);
const struct tm *location_get_modification_time (Location *location,
const gchar *backend_id);
void location_rollback_backend_by (Location *location,
guint steps,
gchar *backend_id,
gboolean parent_chain);
ContainmentType location_contains (Location *location,
const gchar *backend_id);
gint location_add_backend (Location *location,
const gchar *backend_id,
ContainmentType type);
void location_remove_backend (Location *location,
const gchar *backend_id);
void location_rollback_id (Location *location,
gint id);
void location_foreach_backend (Location *location,
LocationBackendCB callback,
gpointer data);
void location_dump_rollback_data (Location *location,
struct tm *date,
guint steps,
gchar *backend_id,
gboolean parent_chain,
FILE *output);
xmlDocPtr location_load_rollback_data (Location *location,
struct tm *date,
guint steps,
gchar *backend_id,
gboolean parent_chain);
GList *location_find_path_from_common_parent (Location *location,
Location *location2);
ContainmentType location_contains (Location *location, gchar *backend_id);
gint location_add_backend (Location *location, gchar *backend_id,
ContainmentType type);
void location_remove_backend (Location *location, gchar *backend_id);
Location *location_get_parent (Location *location);
const gchar *location_get_path (Location *location);
const gchar *location_get_label (Location *location);
const gchar *location_get_id (Location *location);
void location_foreach_backend (Location *location,
LocationBackendCB callback,
gpointer data);
void location_set_id (Location *location,
const gchar *locid);
GList *location_find_path_from_common_parent (Location *location,
Location *location2);
gint location_store_full_snapshot (Location *location);
Location *location_get_parent (Location *location);
const gchar *location_get_path (Location *location);
const gchar *location_get_label (Location *location);
const gchar *location_get_id (Location *location);
GList *location_get_changed_backends (Location *location,
Location *location1);
gboolean location_does_backend_change (Location *location,
Location *location1,
const gchar *backend_id);
void location_set_id (Location *location, const gchar *locid);
ConfigLog *location_get_config_log (Location *location);
gint location_store_full_snapshot (Location *location);
GList *location_get_changed_backends (Location *location,
Location *location1);
gboolean location_does_backend_change (Location *location,
Location *location1,
gchar *backend_id);
ConfigLog *location_get_config_log (Location *location);
void location_garbage_collect (Location *location);
void location_garbage_collect (Location *location);
#endif /* __LOCATION */

View file

@ -95,3 +95,13 @@ parse_date (char *str)
return date;
}
struct tm *
dup_date (const struct tm *date)
{
struct tm *date1;
date1 = g_new (struct tm, 1);
memcpy (date1, date, sizeof (struct tm));
return date1;
}

View file

@ -44,8 +44,8 @@
# define DEBUG_MSG(str, args...)
#endif
gboolean extract_number (char **str, int *number, int digits);
struct tm *parse_date (char *str);
struct tm *dup_date (const struct tm *date);
#endif /* __UTIL_H */

View file

@ -1,3 +1,7 @@
2001-08-20 Bradford Hovinen <hovinen@ximian.com>
* capplet-util.c (get_default_moniker): Update moniker being used
2001-07-30 Bradford Hovinen <hovinen@ximian.com>
* capplet-util.c (capplet_init): Don't sync if we need legacy

View file

@ -334,7 +334,7 @@ get_default_moniker (const gchar *binary)
else tmp++;
if ((tmp1 = strstr (tmp, "-capplet")) != NULL) *tmp1 = '\0';
res = g_strconcat ("archiver:", tmp, NULL);
res = g_strconcat ("archive:user-archive#archiverdb:", tmp, NULL);
g_free (s);
return res;
}

View file

@ -131,7 +131,7 @@ PKG_CHECK_MODULES(CAPPLET, $capplet_modules $PKG_BONOBO_CONF_CHECK)
PKG_CHECK_MODULES(GNOMECC, gnomeui libglade xml gdk_pixbuf gnomecanvaspixbuf $PKG_BONOBO_CHECK gtkhtml >= 0.9)
PKG_CHECK_MODULES(RMHELPER, gnomeui gnomecanvaspixbuf)
PKG_CHECK_MODULES(ARCHIVER, $PKG_BONOBO_CONF_CHECK xml)
PKG_CHECK_MODULES(CONFIG_ARCHIVER, gnome xml)
PKG_CHECK_MODULES(CONFIG_ARCHIVER, bonobo gnome xml)
if test "x$moniker_enable" = "xyes"; then
PKG_CHECK_MODULES(MONIKER, $PKG_BONOBO_CONF_CHECK xml)
@ -276,6 +276,7 @@ capplets/screensaver/Makefile
capplets/screensaver/screensavers/Makefile
capplets/screensaver/screensavers/magic.pl
capplets/sound/Makefile
idl/Makefile
intl/Makefile])
echo "
@ -294,4 +295,3 @@ esac
echo "
"

View file

@ -1,3 +1,8 @@
2001-08-20 Bradford Hovinen <hovinen@ximian.com>
* capplet-dir.c (capplet_control_launch): Update moniker being
used
2001-07-31 Chema Celorio <chema@celorio.com>
* Makefile.am (cappletname): add DISTDIR to install-data-local

View file

@ -478,7 +478,7 @@ capplet_control_launch (const gchar *capplet_name, gchar *window_title)
tmp = g_strdup (capplet_name);
if ((tmp1 = strstr (tmp, "-capplet")) != NULL) *tmp1 = '\0';
moniker = g_strconcat ("archiver:", tmp, NULL);
moniker = g_strconcat ("archive:user-archive#archiverdb:", tmp, NULL);
while ((tmp1 = strchr (tmp, '-'))) *tmp1 = '_';
oaf_iid = g_strconcat ("OAFIID:Bonobo_Control_Capplet_", tmp, NULL);

114
idl/ConfigArchiver.idl Normal file
View file

@ -0,0 +1,114 @@
/* -*- mode: idl; style: linux -*- */
/* Bonobo_ConfigArchiver.idl
* Copyright (C) 2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* 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 __CONFIGARCHIVER_IDL
#define __CONFIGARCHIVER_IDL
%{
#pragma include_defs bonobo/Bonobo.h
%}
#pragma inhibit push
#include <Bonobo_Unknown.idl>
#pragma inhibit pop
module ConfigArchiver {
typedef unsigned long long Time;
typedef sequence<string> StringSeq;
enum ContainmentType {
CONTAIN_NONE, CONTAIN_PARTIAL, CONTAIN_FULL
};
enum StoreType {
STORE_DEFAULT, STORE_FULL, STORE_COMPARE_PARENT, STORE_MASK_PREVIOUS
};
interface BackendList : Bonobo::Unknown {
readonly attribute StringSeq backends;
boolean contains (in string backendId);
void add (in string backendId);
void remove (in string backendId);
void save ();
};
interface Location : Bonobo::Unknown {
readonly attribute Location parent;
readonly attribute string path;
readonly attribute StringSeq backendList;
attribute string label;
attribute string id;
string getStorageFilename (in string backendId,
in boolean isDefaultData);
string getRollbackFilename (in Time time,
in long steps,
in string backendId,
in boolean parentChain);
void rollbackBackends (in Time time,
in long steps,
in StringSeq backendId,
in boolean parentChain);
Time getModificationTime (in string backendId);
ContainmentType contains (in string backendId);
long addBackend (in string backendId,
in ContainmentType type);
void removeBackend (in string backendId);
boolean doesBackendChange (in Location location,
in string backendId);
void garbageCollect ();
void delete ();
};
typedef sequence<Location> LocationSeq;
interface Archive : Bonobo::Unknown {
readonly attribute string prefix;
readonly attribute boolean isGlobal;
readonly attribute BackendList backendList;
attribute Location currentLocation;
attribute string currentLocationId;
Location getLocation (in string locid);
Location createLocation (in string locid,
in string label,
in Location parent);
LocationSeq getChildLocations (in Location parent);
};
};
#endif /* ! __CONFIGARCHIVER_IDL */

6
idl/Makefile.am Normal file
View file

@ -0,0 +1,6 @@
idldir = $(datadir)/idl
idl_DATA = ConfigArchiver.idl
EXTRA_DIST = $(idl_DATA)

View file

@ -1,5 +1,5 @@
archiver/location.c
archiver/main.c
archiver/config-archiver.c
capplets/background/applier.c
capplets/background/background.desktop.in.in
capplets/background/background-properties.glade