Return NULL if fgets returns NULL (dump_log): If both first_old and
2001-08-03 Bradford Hovinen <hovinen@ximian.com> * config-log.c (load_log_entry): Return NULL if fgets returns NULL (dump_log): If both first_old and log_data are NULL, go ahead and dump the file, since nothing has been loaded yet (config_log_garbage_collect): Don't bother dumping the log file or reloading 2001-08-02 Bradford Hovinen <hovinen@ximian.com> * config-log.c (config_log_garbage_collect): Implement (dump_log): Don't dump the old file if first_old is NULL * main.c (main): Support --garbage_collect * location.c (location_garbage_collect): (garbage_collect_cb): Implement
This commit is contained in:
parent
2989b795b3
commit
a1c5aa388f
6 changed files with 185 additions and 36 deletions
|
@ -1,3 +1,21 @@
|
||||||
|
2001-08-03 Bradford Hovinen <hovinen@ximian.com>
|
||||||
|
|
||||||
|
* config-log.c (load_log_entry): Return NULL if fgets returns NULL
|
||||||
|
(dump_log): If both first_old and log_data are NULL, go ahead and
|
||||||
|
dump the file, since nothing has been loaded yet
|
||||||
|
(config_log_garbage_collect): Don't bother dumping the log file or
|
||||||
|
reloading
|
||||||
|
|
||||||
|
2001-08-02 Bradford Hovinen <hovinen@ximian.com>
|
||||||
|
|
||||||
|
* config-log.c (config_log_garbage_collect): Implement
|
||||||
|
(dump_log): Don't dump the old file if first_old is NULL
|
||||||
|
|
||||||
|
* main.c (main): Support --garbage_collect
|
||||||
|
|
||||||
|
* location.c (location_garbage_collect):
|
||||||
|
(garbage_collect_cb): Implement
|
||||||
|
|
||||||
2001-07-31 Bradford Hovinen <hovinen@ximian.com>
|
2001-07-31 Bradford Hovinen <hovinen@ximian.com>
|
||||||
|
|
||||||
* config-log.c: Remove socket-based synchronization system
|
* config-log.c: Remove socket-based synchronization system
|
||||||
|
|
|
@ -518,7 +518,7 @@ config_log_reset_filenames (ConfigLog *config_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* config_log_reload
|
* config_log_reload:
|
||||||
* @config_log:
|
* @config_log:
|
||||||
*
|
*
|
||||||
* Reloads the entire config log, throwing out any newly created entries
|
* Reloads the entire config log, throwing out any newly created entries
|
||||||
|
@ -535,6 +535,84 @@ config_log_reload (ConfigLog *config_log)
|
||||||
do_load (config_log);
|
do_load (config_log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* config_log_garbage_collect:
|
||||||
|
* @config_log:
|
||||||
|
* @backend_id: Backend on which to iterate
|
||||||
|
* @callback: Callback to issue on any log entry to be culled
|
||||||
|
* @data: Arbitrary data to pass to callback
|
||||||
|
*
|
||||||
|
* Iterates through the configuration log and culls excess entries for the given
|
||||||
|
* backend.
|
||||||
|
*
|
||||||
|
* The algorithm we use is the following: We scan entries in temporal order. For
|
||||||
|
* each consecutive pair of entries, let t1 be the time at which the former was
|
||||||
|
* made and t2 be the time of the latter. If K_CONST * (t2 - t1) < t2, then we
|
||||||
|
* delete the former entry and issue the callback. We select K_CONST
|
||||||
|
* appropriately, i.e. a user will likely not want to keep entries separated by
|
||||||
|
* under five minutes for very long, while she may want to keep entries
|
||||||
|
* separated by two weeks for much longer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define K_CONST 15
|
||||||
|
|
||||||
|
void
|
||||||
|
config_log_garbage_collect (ConfigLog *config_log,
|
||||||
|
gchar *backend_id,
|
||||||
|
GarbageCollectCB callback,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GList *node, *list = NULL;
|
||||||
|
ConfigLogEntry *e1, *e2;
|
||||||
|
time_t t1, t2, now;
|
||||||
|
|
||||||
|
g_return_if_fail (config_log != NULL);
|
||||||
|
g_return_if_fail (IS_CONFIG_LOG (config_log));
|
||||||
|
|
||||||
|
if (config_log->p->log_data == NULL)
|
||||||
|
config_log->p->log_data =
|
||||||
|
load_log_entry (config_log, NULL);
|
||||||
|
|
||||||
|
node = config_log->p->log_data;
|
||||||
|
|
||||||
|
/* We build a list of config log nodes to facilitate removing the nodes
|
||||||
|
* from the main cache at a later point
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
node = find_config_log_entry_backend
|
||||||
|
(config_log, node, backend_id);
|
||||||
|
|
||||||
|
if (node == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
list = g_list_prepend (list, node);
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list == NULL) return;
|
||||||
|
|
||||||
|
now = time (NULL);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (K_CONST * (t2 - t1) < 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (list);
|
||||||
|
|
||||||
|
config_log->p->first_old = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the config log entry with the id given, starting at the given
|
/* Find the config log entry with the id given, starting at the given
|
||||||
* node. Return a pointer to the node.
|
* node. Return a pointer to the node.
|
||||||
*/
|
*/
|
||||||
|
@ -663,7 +741,8 @@ load_log_entry (ConfigLog *config_log,
|
||||||
if (feof (config_log->p->file_stream))
|
if (feof (config_log->p->file_stream))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fgets (buffer, 1024, config_log->p->file_stream);
|
if (fgets (buffer, 1024, config_log->p->file_stream) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
entry = g_new0 (ConfigLogEntry, 1);
|
entry = g_new0 (ConfigLogEntry, 1);
|
||||||
entry->date = g_new0 (struct tm, 1);
|
entry->date = g_new0 (struct tm, 1);
|
||||||
|
@ -780,6 +859,7 @@ do_load (ConfigLog *config_log)
|
||||||
g_return_val_if_fail (IS_CONFIG_LOG (config_log), FALSE);
|
g_return_val_if_fail (IS_CONFIG_LOG (config_log), FALSE);
|
||||||
|
|
||||||
config_log->p->file_stream = fopen (config_log->p->filename, "r");
|
config_log->p->file_stream = fopen (config_log->p->filename, "r");
|
||||||
|
config_log->p->first_old = NULL;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -791,8 +871,6 @@ do_load (ConfigLog *config_log)
|
||||||
static void
|
static void
|
||||||
do_unload (ConfigLog *config_log, gboolean write_log)
|
do_unload (ConfigLog *config_log, gboolean write_log)
|
||||||
{
|
{
|
||||||
GList *tmp;
|
|
||||||
|
|
||||||
g_return_if_fail (config_log != NULL);
|
g_return_if_fail (config_log != NULL);
|
||||||
g_return_if_fail (IS_CONFIG_LOG (config_log));
|
g_return_if_fail (IS_CONFIG_LOG (config_log));
|
||||||
|
|
||||||
|
@ -808,13 +886,9 @@ do_unload (ConfigLog *config_log, gboolean write_log)
|
||||||
config_log->p->filename = NULL;
|
config_log->p->filename = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (config_log->p->log_data != NULL) {
|
g_list_foreach (config_log->p->log_data, (GFunc) config_log_entry_destroy, NULL);
|
||||||
tmp = config_log->p->log_data->next;
|
g_list_free (config_log->p->log_data);
|
||||||
config_log_entry_destroy
|
config_log->p->log_data = NULL;
|
||||||
((ConfigLogEntry *) config_log->p->log_data->data);
|
|
||||||
g_list_free_1 (config_log->p->log_data);
|
|
||||||
config_log->p->log_data = tmp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the next id number in the sequence */
|
/* Returns the next id number in the sequence */
|
||||||
|
@ -905,13 +979,16 @@ dump_log (ConfigLog *config_log)
|
||||||
first = first->next)
|
first = first->next)
|
||||||
write_log (output, first->data);
|
write_log (output, first->data);
|
||||||
|
|
||||||
config_log->p->first_old = config_log->p->log_data;
|
if (config_log->p->file_stream != NULL &&
|
||||||
|
((config_log->p->first_old == NULL && config_log->p->log_data == NULL) ||
|
||||||
if (config_log->p->file_stream) {
|
(config_log->p->first_old != NULL && config_log->p->log_data != NULL)))
|
||||||
|
{
|
||||||
rewind (config_log->p->file_stream);
|
rewind (config_log->p->file_stream);
|
||||||
dump_file (config_log->p->file_stream, output);
|
dump_file (config_log->p->file_stream, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config_log->p->first_old = config_log->p->log_data;
|
||||||
|
|
||||||
fclose (output);
|
fclose (output);
|
||||||
|
|
||||||
if (config_log->p->filename)
|
if (config_log->p->filename)
|
||||||
|
|
|
@ -40,6 +40,7 @@ typedef struct _Location Location;
|
||||||
|
|
||||||
typedef gint (*ConfigLogIteratorCB) (ConfigLog *, gint, gchar *,
|
typedef gint (*ConfigLogIteratorCB) (ConfigLog *, gint, gchar *,
|
||||||
struct tm *, gpointer);
|
struct tm *, gpointer);
|
||||||
|
typedef void (*GarbageCollectCB) (ConfigLog *, gchar *, gint, gpointer);
|
||||||
|
|
||||||
struct _ConfigLog
|
struct _ConfigLog
|
||||||
{
|
{
|
||||||
|
@ -81,4 +82,9 @@ void config_log_iterate (ConfigLog *config_log,
|
||||||
void config_log_reset_filenames (ConfigLog *config_log);
|
void config_log_reset_filenames (ConfigLog *config_log);
|
||||||
void config_log_reload (ConfigLog *config_log);
|
void config_log_reload (ConfigLog *config_log);
|
||||||
|
|
||||||
|
void config_log_garbage_collect (ConfigLog *config_log,
|
||||||
|
gchar *backend_id,
|
||||||
|
GarbageCollectCB callback,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
#endif /* __CONFIG_LOG */
|
#endif /* __CONFIG_LOG */
|
||||||
|
|
|
@ -1280,6 +1280,42 @@ location_get_config_log (Location *location)
|
||||||
return location->p->config_log;
|
return location->p->config_log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* location_garbage_collect:
|
||||||
|
* @location:
|
||||||
|
*
|
||||||
|
* Iterates through backends and eliminates excess archived data from the
|
||||||
|
* configuration log and the XML archive
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
garbage_collect_cb (ConfigLog *config_log, gchar *backend_id, gint id, Location *location)
|
||||||
|
{
|
||||||
|
gchar *filename;
|
||||||
|
|
||||||
|
filename = g_strdup_printf ("%s/%08x.xml", location->p->fullpath, id);
|
||||||
|
DEBUG_MSG ("Removing %s", filename);
|
||||||
|
unlink (filename);
|
||||||
|
g_free (filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
location_garbage_collect (Location *location)
|
||||||
|
{
|
||||||
|
GList *node;
|
||||||
|
BackendNote *note;
|
||||||
|
|
||||||
|
g_return_if_fail (location != NULL);
|
||||||
|
g_return_if_fail (IS_LOCATION (location));
|
||||||
|
|
||||||
|
for (node = location->p->contains_list; node != NULL; node = node->next) {
|
||||||
|
note = node->data;
|
||||||
|
config_log_garbage_collect (location->p->config_log,
|
||||||
|
note->backend_id,
|
||||||
|
(GarbageCollectCB) garbage_collect_cb,
|
||||||
|
location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
get_backends_cb (BackendList *backend_list, gchar *backend_id,
|
get_backends_cb (BackendList *backend_list, gchar *backend_id,
|
||||||
Location *location)
|
Location *location)
|
||||||
|
@ -1292,8 +1328,7 @@ get_backends_cb (BackendList *backend_list, gchar *backend_id,
|
||||||
|
|
||||||
/* Construct the directory structure for a given location
|
/* Construct the directory structure for a given location
|
||||||
*
|
*
|
||||||
* FIXME: Better error reporting
|
* FIXME: Better error reporting */
|
||||||
*/
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
do_create (Location *location)
|
do_create (Location *location)
|
||||||
|
|
|
@ -149,4 +149,6 @@ gboolean location_does_backend_change (Location *location,
|
||||||
|
|
||||||
ConfigLog *location_get_config_log (Location *location);
|
ConfigLog *location_get_config_log (Location *location);
|
||||||
|
|
||||||
|
void location_garbage_collect (Location *location);
|
||||||
|
|
||||||
#endif /* __LOCATION */
|
#endif /* __LOCATION */
|
||||||
|
|
|
@ -44,6 +44,7 @@ static gboolean rollback;
|
||||||
static gboolean change_location;
|
static gboolean change_location;
|
||||||
static gboolean rename_location;
|
static gboolean rename_location;
|
||||||
static gboolean push_config;
|
static gboolean push_config;
|
||||||
|
static gboolean garbage_collect;
|
||||||
|
|
||||||
static gboolean add_location;
|
static gboolean add_location;
|
||||||
static gboolean remove_location;
|
static gboolean remove_location;
|
||||||
|
@ -91,6 +92,8 @@ static struct poptOption archiver_operations[] = {
|
||||||
N_("Add a given backend to the given location")},
|
N_("Add a given backend to the given location")},
|
||||||
{"remove-backend", '\0', POPT_ARG_NONE, &remove_backend, 0,
|
{"remove-backend", '\0', POPT_ARG_NONE, &remove_backend, 0,
|
||||||
N_("Remove the given backend from the given location")},
|
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}
|
{NULL, '\0', 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -297,6 +300,12 @@ do_remove_backend (Location *location)
|
||||||
location_remove_backend (location, backend_id);
|
location_remove_backend (location, backend_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_garbage_collect (Location *location)
|
||||||
|
{
|
||||||
|
location_garbage_collect (location);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -365,6 +374,8 @@ main (int argc, char **argv)
|
||||||
do_add_backend (location);
|
do_add_backend (location);
|
||||||
else if (remove_backend)
|
else if (remove_backend)
|
||||||
do_remove_backend (location);
|
do_remove_backend (location);
|
||||||
|
else if (garbage_collect)
|
||||||
|
do_garbage_collect (location);
|
||||||
|
|
||||||
archive_close (archive);
|
archive_close (archive);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue