~ubuntu-branches/ubuntu/oneiric/gconf/oneiric-proposed

« back to all changes in this revision

Viewing changes to backends/xml-backend.c

  • Committer: Bazaar Package Importer
  • Author(s): Takuo KITAME
  • Date: 2002-03-17 01:51:39 UTC
  • Revision ID: james.westby@ubuntu.com-20020317015139-z4f8fdg1hoe049g0
Tags: upstream-1.0.9
ImportĀ upstreamĀ versionĀ 1.0.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* GConf
 
3
 * Copyright (C) 1999, 2000 Red Hat Inc.
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Library General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Library General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Library General Public
 
16
 * License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
 
 
22
#include <gconf/gconf-backend.h>
 
23
#include <gconf/gconf-internals.h>
 
24
#include <gconf/gconf.h>
 
25
 
 
26
#include "xml-cache.h"
 
27
 
 
28
 
 
29
#include <libxml/tree.h>
 
30
#include <libxml/parser.h>
 
31
 
 
32
#include <stdio.h>
 
33
#include <time.h>
 
34
#include <stdlib.h>
 
35
#include <string.h>
 
36
#include <sys/stat.h>
 
37
#include <sys/types.h>
 
38
#include <fcntl.h>
 
39
#include <unistd.h>
 
40
#include <errno.h>
 
41
#include <dirent.h>
 
42
#include <limits.h>
 
43
 
 
44
/*
 
45
 * Overview
 
46
 * 
 
47
 * Basically we have a directory tree underneath an arbitrary root
 
48
 * directory.  The directory tree reflects the configuration
 
49
 * namespace. Each directory contains an XML file which contains
 
50
 * metadata for the directory and the key-value pairs in that
 
51
 * directory.  The magic file in each directory is called %gconf.xml,
 
52
 * and can't clash with the database namespace because names containing
 
53
 * % aren't allowed.  So:
 
54
 *
 
55
 * /
 
56
 *  %gconf.xml
 
57
 *   guppi/
 
58
 *     %gconf.xml
 
59
 *   gnumeric/
 
60
 *     %gconf.xml
 
61
 *
 
62
 *
 
63
 * Locking
 
64
 * 
 
65
 * Locking doesn't _really_ matter because there's only one instance
 
66
 * of the daemon at a time. However, eventually we want a non-daemon
 
67
 * command line tool and library, e.g. for the debconf stuff, 
 
68
 * so we will eventually have locking. I'll figure out then how
 
69
 * it will work.
 
70
 *
 
71
 * Caching
 
72
 *
 
73
 * I haven't decided the best way to do caching yet. As a first cut;
 
74
 * we'll cache the parse tree for any files we've looked at. The cache
 
75
 * will contain time stamps; we'll nuke cache entries that haven't been
 
76
 * used in a while, either in a main loop timeout or by checking whenever 
 
77
 * we add a new cache entry. Parse trees correspond to "directories" in the
 
78
 * configuration namespace.
 
79
 *
 
80
 * A more precise cache will store specific key-value pairs; this cache
 
81
 * will probably contain a pointer to the parse tree node the key-value
 
82
 * pair is inside.
 
83
 *
 
84
 * We'll of course need a "dirty" list of stuff not yet written to disk.
 
85
 *
 
86
 * We'll save the mod time of parse trees when we load them, so we can 
 
87
 * paranoia check that no one has change the file before we save.
 
88
 *
 
89
 * Ideally we could monitor our own process size and also free up
 
90
 * cache whenever we started to use massive RAM. However, not sure
 
91
 * this can be done at all portably. Could possibly have some measure
 
92
 * of parse tree size.
 
93
 *
 
94
 * The libxml parse trees are pretty huge, so in theory we could
 
95
 * "compress" them by extracting all the information we want into a
 
96
 * specialized data structure, then nuking the parse tree. However,
 
97
 * that would add more CPU overhead at load and save time. Anyway, as
 
98
 * a first cut I'm not going to do this, we might do it later.
 
99
 *
 
100
 * Atomic Saving
 
101
 *
 
102
 * We'll want to save atomically by creating a temporary file for the
 
103
 * new file version, renaming the original file, moving the temporary
 
104
 * file into place, then deleting the original file, checking for
 
105
 * errors and mod times along the way.
 
106
 *      
 
107
 * Failed lookup caching
 
108
 *
 
109
 * If a key/directory doesn't exist, we create a cache entry anyway
 
110
 * so we can rapidly re-determine that it doesn't exist.
 
111
 * We also need to save "dirty" nonexistent entries, so we can delete
 
112
 * the stuff off disk.  
 
113
 * 
 
114
 */
 
115
 
 
116
typedef struct _XMLSource XMLSource;
 
117
 
 
118
/* XMLSource **/
 
119
 
 
120
struct _XMLSource {
 
121
  GConfSource source; /* inherit from GConfSource */
 
122
  Cache* cache;
 
123
  gchar* root_dir;
 
124
  guint timeout_id;
 
125
  GConfLock* lock;
 
126
  guint dir_mode;
 
127
  guint file_mode;
 
128
};
 
129
 
 
130
static XMLSource* xs_new       (const gchar* root_dir,
 
131
                                guint dir_mode,
 
132
                                guint file_mode,
 
133
                                GConfLock* lock);
 
134
static void       xs_destroy   (XMLSource* source);
 
135
 
 
136
/*
 
137
 * VTable functions
 
138
 */
 
139
 
 
140
 /* shutdown() is a BSD libc function */
 
141
static void          x_shutdown        (GError** err);
 
142
 
 
143
static GConfSource*  resolve_address (const gchar* address,
 
144
                                      GError** err);
 
145
 
 
146
static void          lock            (GConfSource* source,
 
147
                                      GError** err);
 
148
 
 
149
static void          unlock          (GConfSource* source,
 
150
                                      GError** err);
 
151
 
 
152
static gboolean     readable         (GConfSource* source,
 
153
                                      const gchar* key,
 
154
                                      GError** err);
 
155
 
 
156
static gboolean     writable        (GConfSource* source,
 
157
                                      const gchar* key,
 
158
                                      GError** err);
 
159
 
 
160
static GConfValue*   query_value     (GConfSource* source,
 
161
                                      const gchar* key,
 
162
                                      const gchar** locales,
 
163
                                      gchar** schema_name,
 
164
                                      GError** err);
 
165
 
 
166
static GConfMetaInfo*query_metainfo  (GConfSource* source,
 
167
                                      const gchar* key,
 
168
                                      GError** err);
 
169
 
 
170
static void          set_value       (GConfSource* source,
 
171
                                      const gchar* key,
 
172
                                      GConfValue* value,
 
173
                                      GError** err);
 
174
 
 
175
static GSList*       all_entries    (GConfSource* source,
 
176
                                     const gchar* dir,
 
177
                                     const gchar** locales,
 
178
                                     GError** err);
 
179
 
 
180
static GSList*       all_subdirs     (GConfSource* source,
 
181
                                      const gchar* dir,
 
182
                                      GError** err);
 
183
 
 
184
static void          unset_value     (GConfSource* source,
 
185
                                      const gchar* key,
 
186
                                      const gchar* locale,
 
187
                                      GError** err);
 
188
 
 
189
static gboolean      dir_exists      (GConfSource *source,
 
190
                                      const gchar *dir,
 
191
                                      GError** err);
 
192
 
 
193
static void          remove_dir      (GConfSource* source,
 
194
                                      const gchar* dir,
 
195
                                      GError** err);
 
196
 
 
197
static void          set_schema      (GConfSource* source,
 
198
                                      const gchar* key,
 
199
                                      const gchar* schema_key,
 
200
                                      GError** err);
 
201
 
 
202
static gboolean      sync_all        (GConfSource* source,
 
203
                                      GError** err);
 
204
 
 
205
static void          destroy_source  (GConfSource* source);
 
206
 
 
207
static void          clear_cache     (GConfSource* source);
 
208
 
 
209
static GConfBackendVTable xml_vtable = {
 
210
  x_shutdown,
 
211
  resolve_address,
 
212
  lock,
 
213
  unlock,
 
214
  readable,
 
215
  writable,
 
216
  query_value,
 
217
  query_metainfo,
 
218
  set_value,
 
219
  all_entries,
 
220
  all_subdirs,
 
221
  unset_value,
 
222
  dir_exists,
 
223
  remove_dir,
 
224
  set_schema,
 
225
  sync_all,
 
226
  destroy_source,
 
227
  clear_cache
 
228
};
 
229
 
 
230
static void          
 
231
x_shutdown (GError** err)
 
232
{
 
233
  gconf_log(GCL_DEBUG, _("Unloading XML backend module."));
 
234
}
 
235
 
 
236
static void
 
237
lock (GConfSource* source,
 
238
      GError** err)
 
239
{
 
240
  
 
241
 
 
242
}
 
243
 
 
244
static void
 
245
unlock (GConfSource* source,
 
246
        GError** err)
 
247
{
 
248
 
 
249
 
 
250
}
 
251
 
 
252
static gboolean
 
253
readable (GConfSource* source,
 
254
          const gchar* key,
 
255
          GError** err)
 
256
{
 
257
 
 
258
  return TRUE;
 
259
}
 
260
 
 
261
static gboolean
 
262
writable (GConfSource* source,
 
263
           const gchar* key,
 
264
           GError** err)
 
265
{
 
266
 
 
267
  return TRUE;
 
268
}
 
269
 
 
270
static GConfSource*  
 
271
resolve_address (const gchar* address, GError** err)
 
272
{
 
273
  gchar* root_dir;
 
274
  XMLSource* xsource;
 
275
  GConfSource* source;
 
276
  guint len;
 
277
  gint flags = 0;
 
278
  GConfLock* lock = NULL;
 
279
  guint dir_mode = 0700;
 
280
  guint file_mode = 0600;
 
281
  gchar** address_flags;
 
282
  gchar** iter;
 
283
  gboolean force_readonly;
 
284
  
 
285
  root_dir = gconf_address_resource(address);
 
286
 
 
287
  if (root_dir == NULL)
 
288
    {
 
289
      gconf_set_error(err, GCONF_ERROR_BAD_ADDRESS, _("Couldn't find the XML root directory in the address `%s'"), address);
 
290
      return NULL;
 
291
    }
 
292
 
 
293
  /* Chop trailing '/' to canonicalize */
 
294
  len = strlen(root_dir);
 
295
 
 
296
  if (root_dir[len-1] == '/')
 
297
    root_dir[len-1] = '\0';
 
298
 
 
299
  if (mkdir(root_dir, dir_mode) < 0)
 
300
    {
 
301
      if (errno != EEXIST)
 
302
        {
 
303
          gconf_set_error(err, GCONF_ERROR_FAILED,
 
304
                          _("Could not make directory `%s': %s"),
 
305
                          (gchar*)root_dir, strerror(errno));
 
306
          g_free(root_dir);
 
307
          return NULL;
 
308
        }
 
309
      else
 
310
        {
 
311
          /* Already exists, base our dir_mode on it */
 
312
          struct stat statbuf;
 
313
          if (stat(root_dir, &statbuf) == 0)
 
314
            {
 
315
              dir_mode = mode_t_to_mode(statbuf.st_mode);
 
316
              /* dir_mode without search bits */
 
317
              file_mode = dir_mode & (~0111); 
 
318
            }
 
319
        }
 
320
    }
 
321
 
 
322
  force_readonly = FALSE;
 
323
  
 
324
  address_flags = gconf_address_flags (address);  
 
325
  if (address_flags)
 
326
    {
 
327
      iter = address_flags;
 
328
      while (*iter)
 
329
        {
 
330
          if (strcmp (*iter, "readonly") == 0)
 
331
            {
 
332
              force_readonly = TRUE;
 
333
              break;
 
334
            }
 
335
 
 
336
          ++iter;
 
337
        }
 
338
    }
 
339
 
 
340
  g_strfreev (address_flags);
 
341
 
 
342
  {
 
343
    /* See if we're writable */
 
344
    gboolean writable;
 
345
    int fd;
 
346
    gchar* testfile;
 
347
 
 
348
    writable = FALSE;
 
349
    
 
350
    if (!force_readonly)
 
351
      {
 
352
        testfile = g_strconcat(root_dir, "/.testing.writeability", NULL);    
 
353
        
 
354
        fd = open(testfile, O_CREAT|O_WRONLY, S_IRWXU);
 
355
        
 
356
        if (fd >= 0)
 
357
          {
 
358
            writable = TRUE;
 
359
            close(fd);
 
360
          }
 
361
        
 
362
        unlink(testfile);
 
363
        
 
364
        g_free(testfile);
 
365
      }
 
366
    
 
367
    if (writable)
 
368
      flags |= GCONF_SOURCE_ALL_WRITEABLE;
 
369
 
 
370
    /* We only do locking if it's writable,
 
371
       which is sort of broken but close enough
 
372
    */
 
373
    if (writable)
 
374
      {
 
375
        gchar* lockdir;
 
376
 
 
377
        lockdir = gconf_concat_dir_and_key(root_dir, "%gconf-xml-backend.lock");
 
378
        
 
379
        lock = gconf_get_lock(lockdir, err);
 
380
 
 
381
        if (lock != NULL)
 
382
          gconf_log(GCL_DEBUG, "Acquired lock directory `%s'", lockdir);
 
383
        
 
384
        g_free(lockdir);
 
385
        
 
386
        if (lock == NULL)
 
387
          {
 
388
            g_free(root_dir);
 
389
            return NULL;
 
390
          }
 
391
      }
 
392
  }
 
393
 
 
394
  {
 
395
    /* see if we're readable */
 
396
    gboolean readable = FALSE;
 
397
    DIR* d;
 
398
 
 
399
    d = opendir(root_dir);
 
400
 
 
401
    if (d != NULL)
 
402
      {
 
403
        readable = TRUE;
 
404
        closedir(d);
 
405
      }
 
406
    
 
407
    if (readable)
 
408
      flags |= GCONF_SOURCE_ALL_READABLE;
 
409
  }
 
410
 
 
411
  if (!(flags & GCONF_SOURCE_ALL_READABLE) &&
 
412
      !(flags & GCONF_SOURCE_ALL_WRITEABLE))
 
413
    {
 
414
      gconf_set_error(err, GCONF_ERROR_BAD_ADDRESS, _("Can't read from or write to the XML root directory in the address `%s'"), address);
 
415
      g_free(root_dir);
 
416
      return NULL;
 
417
    }  
 
418
  
 
419
  /* Create the new source */
 
420
 
 
421
  xsource = xs_new(root_dir, dir_mode, file_mode, lock);
 
422
 
 
423
  gconf_log(GCL_DEBUG,
 
424
            _("Directory/file permissions for XML source at root %s are: %o/%o"),
 
425
            root_dir, dir_mode, file_mode);
 
426
  
 
427
  source = (GConfSource*)xsource;
 
428
 
 
429
  source->flags = flags;
 
430
  
 
431
  g_free(root_dir);
 
432
  
 
433
  return source;
 
434
}
 
435
 
 
436
static GConfValue* 
 
437
query_value (GConfSource* source,
 
438
             const gchar* key,
 
439
             const gchar** locales,
 
440
             gchar** schema_name,
 
441
             GError** err)
 
442
{
 
443
  XMLSource* xs = (XMLSource*)source;
 
444
  gchar* parent;
 
445
  Dir* dir;
 
446
  GError* error = NULL;
 
447
 
 
448
  parent = gconf_key_directory(key);
 
449
  
 
450
  g_assert(parent != NULL);
 
451
  
 
452
  dir = cache_lookup(xs->cache, parent, FALSE, &error);
 
453
 
 
454
  /* We DO NOT want to return an error unless it represents a general
 
455
     problem with the backend; since we don't want to report stuff
 
456
     like "this key doesn't exist yet" - however this is a maintenance
 
457
     problem, since some errors may be added that need reporting. */
 
458
  if (error != NULL)
 
459
    {
 
460
      gconf_log(GCL_WARNING, "%s", error->message);
 
461
      g_error_free(error);
 
462
      error = NULL;
 
463
    }
 
464
  
 
465
  g_free(parent);
 
466
  parent = NULL;
 
467
  
 
468
  if (dir != NULL)
 
469
    {
 
470
      const gchar* relative_key;
 
471
      GConfValue* retval;
 
472
      
 
473
      relative_key = gconf_key_key(key);
 
474
 
 
475
      retval = dir_get_value(dir, relative_key, locales, schema_name, &error);
 
476
 
 
477
      /* perhaps we should be reporting this error... */
 
478
      if (error != NULL)
 
479
        {
 
480
          gconf_log(GCL_WARNING, "%s", error->message);
 
481
          g_error_free(error);
 
482
          error = NULL;
 
483
        }
 
484
      
 
485
      return retval;
 
486
    }
 
487
  else
 
488
    return NULL;
 
489
}
 
490
 
 
491
static GConfMetaInfo*
 
492
query_metainfo  (GConfSource* source, const gchar* key,
 
493
                 GError** err)
 
494
{
 
495
  XMLSource* xs = (XMLSource*)source;
 
496
  gchar* parent;
 
497
  Dir* dir;
 
498
 
 
499
  parent = gconf_key_directory(key);
 
500
 
 
501
  if (parent != NULL)
 
502
    {
 
503
      dir = cache_lookup(xs->cache, parent, FALSE, err);
 
504
      g_free(parent);
 
505
      parent = NULL;
 
506
      
 
507
      if (dir != NULL)
 
508
        {
 
509
          const gchar* relative_key;
 
510
      
 
511
          relative_key = gconf_key_key (key);
 
512
 
 
513
          return dir_get_metainfo (dir, relative_key, err);
 
514
        }
 
515
    }
 
516
 
 
517
  /* No metainfo found */
 
518
  return NULL;
 
519
}
 
520
 
 
521
static void          
 
522
set_value (GConfSource* source, const gchar* key, GConfValue* value,
 
523
           GError** err)
 
524
{
 
525
  XMLSource* xs = (XMLSource*)source;
 
526
  Dir* dir;
 
527
  gchar* parent;
 
528
  
 
529
  g_return_if_fail(value != NULL);
 
530
  g_return_if_fail(source != NULL);
 
531
  
 
532
  parent = gconf_key_directory(key);
 
533
  
 
534
  g_assert(parent != NULL);
 
535
  
 
536
  dir = cache_lookup(xs->cache, parent, TRUE, err);
 
537
  
 
538
  g_free(parent);
 
539
  parent = NULL;
 
540
 
 
541
  if (dir == NULL)
 
542
    {
 
543
      g_return_if_fail((err == NULL || *err != NULL));
 
544
      return;
 
545
    }
 
546
  else
 
547
    {
 
548
      const gchar* relative_key;
 
549
      
 
550
      relative_key = gconf_key_key(key);
 
551
      
 
552
      dir_set_value(dir, relative_key, value, err);
 
553
    }
 
554
}
 
555
 
 
556
 
 
557
static GSList*             
 
558
all_entries    (GConfSource* source,
 
559
                const gchar* key,
 
560
                const gchar** locales,
 
561
                GError** err)
 
562
{
 
563
  XMLSource* xs = (XMLSource*)source;
 
564
  Dir* dir;
 
565
 
 
566
  dir = cache_lookup(xs->cache, key, FALSE, err);
 
567
  
 
568
  if (dir == NULL)
 
569
    return NULL;
 
570
  else
 
571
    return dir_all_entries(dir, locales, err);
 
572
}
 
573
 
 
574
static GSList*
 
575
all_subdirs     (GConfSource* source,
 
576
                 const gchar* key,
 
577
                 GError** err)
 
578
{
 
579
  Dir* dir;
 
580
  XMLSource* xs = (XMLSource*)source;
 
581
 
 
582
  dir = cache_lookup (xs->cache, key, FALSE, err);
 
583
  
 
584
  if (dir == NULL)
 
585
    return NULL;
 
586
  else
 
587
    return dir_all_subdirs (dir, err);
 
588
}
 
589
 
 
590
static void          
 
591
unset_value     (GConfSource* source,
 
592
                 const gchar* key,
 
593
                 const gchar* locale,
 
594
                 GError** err)
 
595
{
 
596
  XMLSource* xs = (XMLSource*)source;
 
597
  Dir* dir;
 
598
  gchar* parent;
 
599
 
 
600
  gconf_log(GCL_DEBUG, "XML backend: unset value `%s'", key);
 
601
  
 
602
  parent = gconf_key_directory(key);
 
603
  
 
604
  dir = cache_lookup(xs->cache, parent, FALSE, err);
 
605
 
 
606
  g_free(parent);
 
607
  
 
608
  if (dir == NULL)
 
609
    return;
 
610
  else
 
611
    {
 
612
      const gchar* relative_key;
 
613
  
 
614
      relative_key = gconf_key_key(key);
 
615
 
 
616
      dir_unset_value(dir, relative_key, locale, err);
 
617
    }
 
618
}
 
619
 
 
620
static gboolean
 
621
dir_exists      (GConfSource*source,
 
622
                 const gchar* key,
 
623
                 GError** err)
 
624
{
 
625
  XMLSource *xs = (XMLSource*)source;
 
626
  Dir* dir;
 
627
  
 
628
  dir = cache_lookup(xs->cache, key, FALSE, err);
 
629
  
 
630
  return (dir != NULL);
 
631
}  
 
632
 
 
633
static void          
 
634
remove_dir      (GConfSource* source,
 
635
                 const gchar* key,
 
636
                 GError** err)
 
637
{
 
638
  XMLSource* xs = (XMLSource*)source;
 
639
  Dir* dir;
 
640
  
 
641
  dir = cache_lookup(xs->cache, key, FALSE, err);
 
642
  
 
643
  if (dir == NULL)
 
644
    return;
 
645
  else
 
646
    {
 
647
      dir_mark_deleted(dir);
 
648
    }
 
649
}
 
650
 
 
651
static void          
 
652
set_schema      (GConfSource* source,
 
653
                 const gchar* key,
 
654
                 const gchar* schema_key,
 
655
                 GError** err)
 
656
{
 
657
  XMLSource* xs = (XMLSource*)source;
 
658
 
 
659
  Dir* dir;
 
660
  gchar* parent;
 
661
  
 
662
  g_return_if_fail(schema_key != NULL);
 
663
 
 
664
  parent = gconf_key_directory(key);
 
665
  
 
666
  g_assert(parent != NULL);
 
667
  
 
668
  dir = cache_lookup(xs->cache, parent, TRUE, err);
 
669
  
 
670
  g_free(parent);
 
671
  parent = NULL;
 
672
 
 
673
  if (dir == NULL)
 
674
    return; /* error should be set */
 
675
  else
 
676
    {
 
677
      const gchar* relative_key;
 
678
      
 
679
      relative_key = gconf_key_key(key);
 
680
      
 
681
      dir_set_schema(dir, relative_key, schema_key, err);
 
682
    }
 
683
}
 
684
 
 
685
static gboolean      
 
686
sync_all        (GConfSource* source,
 
687
                 GError** err)
 
688
{
 
689
  XMLSource* xs = (XMLSource*)source;
 
690
 
 
691
  return cache_sync(xs->cache, err);
 
692
}
 
693
 
 
694
static void          
 
695
destroy_source  (GConfSource* source)
 
696
{
 
697
  xs_destroy((XMLSource*)source);
 
698
}
 
699
 
 
700
static void
 
701
clear_cache     (GConfSource* source)
 
702
{
 
703
  XMLSource* xs = (XMLSource*)source;
 
704
 
 
705
  /* clean all entries older than 0 seconds */
 
706
  cache_clean(xs->cache, 0);
 
707
}
 
708
 
 
709
/* Initializer */
 
710
 
 
711
G_MODULE_EXPORT const gchar*
 
712
g_module_check_init (GModule *module)
 
713
{
 
714
  gconf_log(GCL_DEBUG, _("Initializing XML backend module"));
 
715
 
 
716
  return NULL;
 
717
}
 
718
 
 
719
G_MODULE_EXPORT GConfBackendVTable* 
 
720
gconf_backend_get_vtable(void)
 
721
{
 
722
  return &xml_vtable;
 
723
}
 
724
 
 
725
/* ****************************************************/
 
726
 
 
727
/*
 
728
 *  XMLSource
 
729
 */ 
 
730
 
 
731
/* This timeout periodically cleans up
 
732
   the old cruft in the cache */
 
733
static gboolean
 
734
cleanup_timeout(gpointer data)
 
735
{
 
736
  XMLSource* xs = (XMLSource*)data;
 
737
 
 
738
  cache_clean(xs->cache, 60*5 /* 5 minutes */);
 
739
 
 
740
  return TRUE;
 
741
}
 
742
 
 
743
static XMLSource*
 
744
xs_new       (const gchar* root_dir, guint dir_mode, guint file_mode, GConfLock* lock)
 
745
{
 
746
  XMLSource* xs;
 
747
 
 
748
  g_return_val_if_fail(root_dir != NULL, NULL);
 
749
 
 
750
  xs = g_new0(XMLSource, 1);
 
751
 
 
752
  xs->root_dir = g_strdup(root_dir);
 
753
 
 
754
  xs->cache = cache_new(xs->root_dir, dir_mode, file_mode);
 
755
 
 
756
  xs->timeout_id = g_timeout_add(1000*60*5, /* 1 sec * 60 s/min * 5 min */
 
757
                                 cleanup_timeout,
 
758
                                 xs);
 
759
 
 
760
  xs->lock = lock;
 
761
 
 
762
  xs->dir_mode = dir_mode;
 
763
  xs->file_mode = file_mode;
 
764
  
 
765
  return xs;
 
766
}
 
767
 
 
768
static void
 
769
xs_destroy   (XMLSource* xs)
 
770
{
 
771
  GError* error = NULL;
 
772
  
 
773
  g_return_if_fail(xs != NULL);
 
774
 
 
775
  /* do this first in case we're in a "fast cleanup just before exit"
 
776
     situation */
 
777
  if (xs->lock != NULL && !gconf_release_lock(xs->lock, &error))
 
778
    {
 
779
      gconf_log(GCL_ERR, _("Failed to give up lock on XML dir `%s': %s"),
 
780
                xs->root_dir, error->message);
 
781
      g_error_free(error);
 
782
      error = NULL;
 
783
    }
 
784
  
 
785
  if (!g_source_remove(xs->timeout_id))
 
786
    {
 
787
      /* should not happen, don't translate */
 
788
      gconf_log(GCL_ERR, "timeout not found to remove?");
 
789
    }
 
790
  
 
791
  cache_destroy(xs->cache);
 
792
  g_free(xs->root_dir);
 
793
  g_free(xs);
 
794
}