Document the new options: --modid-path, --load-untested
[captive.git] / src / libcaptive / client / parent-connector.c
1 /* $Id$
2  * fs object sandbox parents reconnections to their sandbox slave peers
3  * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "parent-connector.h"   /* self */
23 #include <glib/gmessages.h>
24
25
26 /* g_object_get_data() 'key': */
27 #define CAPTIVE_PARENT_CONNECTOR_CORBA_OBJECTP             "captive_parent_connector-corba_objectp"     /* &CORBA_Object */
28 #define CAPTIVE_PARENT_CONNECTOR_CAPTIVE_VFS_PARENT_OBJECT "captive_parent_connector-captive_vfs_parent_object" /* &CaptiveVfsParentObject */
29 #define CAPTIVE_PARENT_CONNECTOR_DIRTY                     "captive_parent_connector-dirty"     /* GINT_TO_POINTER(0/1) */
30 #define CAPTIVE_PARENT_CONNECTOR_BROKEN                    "captive_parent_connector-broken"    /* GINT_TO_POINTER(0/1) */
31 #define CAPTIVE_PARENT_CONNECTOR_SELF_REFS                 "captive_parent_connector-self_refs" /* GINT_TO_POINTER(count) */
32
33
34 /*
35  * vfs signal <detach>
36  * vfs signal <cease>
37  * vfs signal <abort>
38  * 
39  * connector state vfs          yes/no
40  * connector state corba_object yes/no
41  * connector state dirty        yes/no
42  * 
43  *                 vfs     handle  dirty   oper.   detach  cease   abort
44  * disconnected    N       N       N       opn_*   discon. discon. discon.
45  * broken          N       N       Y       broken  broken  broken  broken
46  * N/A             N       Y       N
47  * N/A             N       Y       Y
48  * closed_clean    Y       N       N       X       X       discon. discon.
49  * closed_dirty    Y       N       Y       X       X       discon. broken
50  * opened_clean    Y       Y       N       opn_*   cls_cln X       discon.
51  * opened_dirty    Y       Y       Y       opn_drt cls_drt X       broken
52  * 
53  * init->disconnected
54  * 
55  * <detach>[VFS shutdown]<cease>
56  * <detach>[failure]<abort>
57  * [failure]<abort>
58  * 
59  * 
60  * sandbox master GObject hierarchy (horizontal=dervived):
61  *         DirectoryParent----------------------------------->Directory->GObject
62  *                        \->ParentConnector->GTypeInterface   |
63  *                                  | [ref.]                   | [reference]
64  *                                 VfsParent----------------->Vfs->GObject
65  * 
66  * sandbox master GObject reconnections signalling:
67  *               VfsParent -> ParentConnector
68  *         ParentConnector -> DirectoryParent
69  * sandbox master reconnection requests:
70  *         DirectoryParent -> ParentConnector
71  *         ParentConnector -> VfsParent
72  * 
73  * CORBA/ORBit connections:
74  *         sandbox master                   |  sandbox slave (restartable)
75  *         ---------------------------------|-----------------------------------
76  *         DirectoryParent--Directory_stub <-> Directory_servant--DirectorySlave
77  *               VfsParent--------Vfs_stub <->       Vfs_servant--VfsSlave
78  * 
79  * sandbox slave GObject hierarchy (horizontal=dervived):
80  *         DirectorySlave->Directory->GObject
81  *                          | [reference]
82  *               VfsSlave->Vfs->GObject
83  */
84
85
86 static GnomeVFSResult captive_parent_connector_handler_open(CaptiveParentConnector *captive_parent_connector);
87 static GnomeVFSResult captive_parent_connector_handler_close(CaptiveParentConnector *captive_parent_connector);
88
89
90 static void captive_parent_connector_iface_init(CaptiveParentConnectorIface *captive_parent_connector_iface)
91 {
92         captive_parent_connector_iface->open=captive_parent_connector_handler_open;
93         captive_parent_connector_iface->close=captive_parent_connector_handler_close;
94 }
95
96
97 GType captive_parent_connector_get_type(void)
98 {
99 static GType captive_parent_connector_type=0;
100
101         if (!captive_parent_connector_type) {
102 static const GTypeInfo captive_parent_connector_info={
103                                 sizeof(CaptiveParentConnectorIface),
104                                 (GBaseInitFunc)captive_parent_connector_iface_init,     /* base_init */
105                                 NULL,   /* base_finalize */
106                                 NULL,   /* iface_init */
107                                 NULL,   /* iface_finalize */
108                                 NULL,   /* iface_data */
109                                 0,      /* instance_size */
110                                 0,      /* n_preallocs */
111                                 NULL,   /* instance_init */
112                                 };
113
114                 captive_parent_connector_type=g_type_register_static(G_TYPE_INTERFACE,
115                                 "CaptiveParentConnector",&captive_parent_connector_info,0);
116                 }
117
118         return captive_parent_connector_type;
119 }
120
121 static void captive_parent_connector_vfs_signals_disconnect(CaptiveParentConnector *captive_parent_connector);
122
123 static void captive_parent_connector_vfs_detach(CaptiveVfsParentObject *captive_vfs_parent_object,
124                 CaptiveParentConnector *captive_parent_connector)
125 {
126         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
127         g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
128         g_return_if_fail(NULL==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector)
129                         || captive_vfs_parent_object==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector));
130
131         /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
132                 /* NOP */;
133         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
134                 /* NOP */;
135         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED))
136                 /* NOP */;
137         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED)) {
138                 (*CAPTIVE_PARENT_CONNECTOR_GET_IFACE(captive_parent_connector)->close)(captive_parent_connector);       /* errors ignored */
139                 g_assert(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED));
140                 }
141         else g_assert_not_reached();
142 }
143
144 static void captive_parent_connector_vfs_cease(CaptiveVfsParentObject *captive_vfs_parent_object,
145                 CaptiveParentConnector *captive_parent_connector)
146 {
147         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
148         g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
149         g_return_if_fail(NULL==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector)
150                         || captive_vfs_parent_object==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector));
151
152         /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
153                 /* NOP */;
154         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
155                 /* NOP */;
156         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED)) {
157                 g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_DIRTY,
158                                 GINT_TO_POINTER(FALSE));
159                 }
160         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED))
161                 g_assert_not_reached();
162         else g_assert_not_reached();
163
164         captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
165 }
166
167 static void captive_parent_connector_vfs_abort(CaptiveVfsParentObject *captive_vfs_parent_object,
168                 CaptiveParentConnector *captive_parent_connector)
169 {
170         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
171         g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
172         g_return_if_fail(NULL==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector)
173                         || captive_vfs_parent_object==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector));
174
175         if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_DIRTY_OR_OPENED_DIRTY))
176                 g_warning(_("Filesystem crash broke dirty object: %s"),
177                                 (*CAPTIVE_PARENT_CONNECTOR_GET_IFACE(captive_parent_connector)->get_pathname)(captive_parent_connector));
178
179         /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
180                 /* NOP */;
181         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
182                 /* NOP */;
183         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_CLEAN))
184                 /* NOP */;      /* -> DISCONNECTED */
185         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_DIRTY)) {
186                 /* -> BROKEN */
187                 /* Ensure to never become VFS-capable Connector from BROKEN state. */
188                 g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_BROKEN,
189                                 GINT_TO_POINTER(TRUE));
190                 }
191         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED)) {
192                 (*CAPTIVE_PARENT_CONNECTOR_GET_IFACE(captive_parent_connector)->close)(captive_parent_connector);       /* errors ignored */
193                 g_assert(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED));
194                 }
195         else g_assert_not_reached();
196
197         captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
198 }
199
200 static void captive_parent_connector_vfs_signals_connect(CaptiveParentConnector *captive_parent_connector)
201 {
202 CaptiveVfsParentObject *captive_vfs_parent_object;
203
204         g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
205
206         captive_vfs_parent_object=captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector);
207
208         /* Prevent multiple equivalent signal handlers. */
209         captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
210
211         g_signal_connect(captive_vfs_parent_object,"detach",
212                         G_CALLBACK(captive_parent_connector_vfs_detach),captive_parent_connector);      /* c_handler,data */
213         g_signal_connect(captive_vfs_parent_object,"cease",
214                         G_CALLBACK(captive_parent_connector_vfs_cease),captive_parent_connector);       /* c_handler,data */
215         g_signal_connect(captive_vfs_parent_object,"abort",
216                         G_CALLBACK(captive_parent_connector_vfs_abort),captive_parent_connector);       /* c_handler,data */
217 }
218
219 static void captive_parent_connector_vfs_signals_disconnect(CaptiveParentConnector *captive_parent_connector)
220 {
221 CaptiveVfsParentObject *captive_vfs_parent_object;
222 gint self_refs;
223
224         g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
225
226         captive_vfs_parent_object=captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector);
227
228         g_signal_handlers_disconnect_by_func(captive_vfs_parent_object,
229                         G_CALLBACK(captive_parent_connector_vfs_detach),captive_parent_connector);      /* func,data */
230         g_signal_handlers_disconnect_by_func(captive_vfs_parent_object,
231                         G_CALLBACK(captive_parent_connector_vfs_cease),captive_parent_connector);       /* func,data */
232         g_signal_handlers_disconnect_by_func(captive_vfs_parent_object,
233                         G_CALLBACK(captive_parent_connector_vfs_abort),captive_parent_connector);       /* func,data */
234
235         /* Do not 'while'-cycle the loop by 1-decreasing as we cannot g_object_get_data()
236          * on fully unreffed GObject.
237          */
238         if ((self_refs=GPOINTER_TO_INT(
239                         g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_SELF_REFS)))) {
240                 g_assert(self_refs>0);
241                 g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_SELF_REFS,
242                                 GINT_TO_POINTER(0));
243                 while (self_refs--) {
244                         /* Undo captive_directory_close() / captive_file_close(): */
245                         g_object_ref(captive_vfs_parent_object);
246                         /* Cause g_object_last_unref(): */
247                         g_object_unref(captive_parent_connector);
248                         }
249                 }
250 }
251
252
253 void captive_parent_connector_init(CaptiveParentConnector *captive_parent_connector,
254                 CORBA_Object *corba_objectp,CaptiveVfsParentObject *captive_vfs_parent_object)
255 {
256         g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
257         g_return_if_fail(corba_objectp!=NULL);
258         g_return_if_fail(/* CORBA_Object_is_nil() */ *corba_objectp==CORBA_OBJECT_NIL);
259         g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
260
261         g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_CORBA_OBJECTP,
262                         corba_objectp);
263         g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_CAPTIVE_VFS_PARENT_OBJECT,
264                         captive_vfs_parent_object);
265         g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_DIRTY,
266                         GINT_TO_POINTER(FALSE));
267
268         g_assert(
269                         captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED_OR_CLOSED_CLEAN));
270 }
271
272
273 /* Abort dispose()? */
274 gboolean captive_parent_connector_dispose(CaptiveParentConnector *captive_parent_connector)
275 {
276         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),FALSE);
277
278         if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_DIRTY)) {
279 CaptiveVfsParentObject *captive_vfs_parent_object;
280
281                 captive_vfs_parent_object=captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector);
282
283                 /* Cancel g_object_last_unref(): */
284                 g_object_ref(captive_parent_connector);
285                 /* Simulate captive_directory_close() / captive_file_close(): */
286                 g_object_unref(captive_vfs_parent_object);
287                 g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_SELF_REFS,
288                                 GINT_TO_POINTER(1+GPOINTER_TO_INT(
289                                                 g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_SELF_REFS))));
290                 return TRUE;    /* abort dispose() */
291                 }
292
293         captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
294         return FALSE;   /* continue dispose() */
295 }
296
297
298 void captive_parent_connector_finalize(CaptiveParentConnector *captive_parent_connector)
299 {
300         g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
301
302         g_assert(captive_parent_connector_is_state(
303                         captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED_OR_BROKEN_OR_CLOSED));
304         /* Should have been catched by captive_parent_connector_dispose(): */
305         g_assert(!captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_DIRTY));
306
307         captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
308 }
309
310
311 GnomeVFSResult captive_parent_connector_connect(CaptiveParentConnector *captive_parent_connector)
312 {
313 GnomeVFSResult r;
314
315         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),GNOME_VFS_ERROR_BAD_PARAMETERS);
316
317         if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED)) {
318                 if (GNOME_VFS_OK!=(r=captive_vfs_parent_object_connect(
319                                 captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector))))
320                         return r;
321                 g_assert(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_CLEAN));
322                 }
323
324         /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
325                 g_assert_not_reached();
326         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
327                 return GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE;
328         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED))
329                 return GNOME_VFS_OK;
330         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED))
331                 return GNOME_VFS_OK;
332         else g_assert_not_reached();
333
334         /* NOTREACHED */
335         return GNOME_VFS_ERROR_INTERNAL;
336 }
337
338
339 GnomeVFSResult captive_parent_connector_open(CaptiveParentConnector *captive_parent_connector)
340 {
341 GnomeVFSResult r;
342
343         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),GNOME_VFS_ERROR_BAD_PARAMETERS);
344
345         if (GNOME_VFS_OK!=(r=captive_parent_connector_connect(captive_parent_connector)))
346                 return r;
347
348         if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED)) {
349                 if (GNOME_VFS_OK!=(r=(*CAPTIVE_PARENT_CONNECTOR_GET_IFACE(captive_parent_connector)->open)(captive_parent_connector)))
350                         return r;
351                 g_assert(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED));
352                 }
353
354         /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
355                 g_assert_not_reached();
356         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
357                 g_assert_not_reached();
358         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED))
359                 g_assert_not_reached();
360         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED))
361                 return GNOME_VFS_OK;
362         else g_assert_not_reached();
363
364         /* NOTREACHED */
365         return GNOME_VFS_ERROR_INTERNAL;
366 }
367
368
369 GnomeVFSResult captive_parent_connector_close(CaptiveParentConnector *captive_parent_connector)
370 {
371 GnomeVFSResult r;
372
373         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),GNOME_VFS_ERROR_BAD_PARAMETERS);
374
375         if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED)) {
376                 if (GNOME_VFS_OK!=(r=(*CAPTIVE_PARENT_CONNECTOR_GET_IFACE(captive_parent_connector)->close)(captive_parent_connector)))
377                         return r;
378                 g_assert(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED));
379                 }
380
381         /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
382                 return GNOME_VFS_OK;
383         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
384                 return GNOME_VFS_OK;
385         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED))
386                 return GNOME_VFS_OK;
387         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED))
388                 g_assert_not_reached();
389         else g_assert_not_reached();
390
391         /* NOTREACHED */
392         return GNOME_VFS_ERROR_INTERNAL;
393 }
394
395
396 void captive_parent_connector_set_dirty(CaptiveParentConnector *captive_parent_connector)
397 {
398         g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
399
400         g_return_if_fail(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED));
401
402         g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_DIRTY,
403                         GINT_TO_POINTER(TRUE));
404 }
405
406
407 static GnomeVFSResult captive_parent_connector_handler_open(CaptiveParentConnector *captive_parent_connector)
408 {
409         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),GNOME_VFS_ERROR_BAD_PARAMETERS);
410
411         /* Handler should have 'opened' us. */
412
413         /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
414                 g_assert_not_reached();
415         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
416                 g_assert_not_reached();
417         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED))
418                 g_assert_not_reached(); /* Parent handler failed. */
419         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED)) {
420                 captive_parent_connector_vfs_signals_connect(captive_parent_connector);
421                 return GNOME_VFS_OK;
422                 }
423         else g_assert_not_reached();
424
425         /* NOTREACHED */
426         return GNOME_VFS_ERROR_INTERNAL;
427 }
428
429
430 static GnomeVFSResult captive_parent_connector_handler_close(CaptiveParentConnector *captive_parent_connector)
431 {
432         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),GNOME_VFS_ERROR_BAD_PARAMETERS);
433
434         /* Handler should have 'closed' us. */
435
436         /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
437                 return GNOME_VFS_OK;
438         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
439                 return GNOME_VFS_OK;
440         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED))
441                 return GNOME_VFS_OK;
442         else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED))
443                 g_assert_not_reached();
444         else g_assert_not_reached();
445
446         /* NOTREACHED */
447         return GNOME_VFS_ERROR_INTERNAL;
448 }
449
450
451 CaptiveVfsParentObject *captive_parent_connector_get_captive_vfs_parent_object
452                 (CaptiveParentConnector *captive_parent_connector)
453 {
454 CaptiveVfsParentObject *r;
455
456         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),NULL);
457
458         r=g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_CAPTIVE_VFS_PARENT_OBJECT);
459         g_assert(CAPTIVE_VFS_PARENT_IS_OBJECT(r));
460
461         return r;
462 }
463
464
465 CORBA_Object captive_parent_connector_get_corba_object(CaptiveParentConnector *captive_parent_connector)
466 {
467 CORBA_Object *rp;
468
469         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),NULL);
470
471         rp=g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_CORBA_OBJECTP);
472         g_assert(rp!=NULL);
473         /* '*rp' may be NULL */
474
475         return *rp;
476 }
477
478
479 gboolean captive_parent_connector_get_dirty(CaptiveParentConnector *captive_parent_connector)
480 {
481 gpointer r_gpointer;
482 gint r_gint;
483
484         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),FALSE);
485
486         r_gpointer=g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_DIRTY);
487         r_gint=GPOINTER_TO_INT(r_gpointer);
488         g_assert(r_gint==TRUE || r_gint==FALSE);
489
490         return r_gint;
491 }
492
493
494 gboolean captive_parent_connector_is_state(CaptiveParentConnector *captive_parent_connector,
495                 CaptiveParentConnectorFlagWant vfs_want,
496                 CaptiveParentConnectorFlagWant corba_object_want,CaptiveParentConnectorFlagWant dirty_want)
497 {
498         g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),FALSE);
499
500         if (vfs_want!=CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ANY) {
501 CaptiveVfsParentObject *captive_vfs_parent_object;
502
503                 captive_vfs_parent_object=captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector);
504                 if ((vfs_want==CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ON)!=
505                                 (!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_BROKEN))
506                                                 && /* !CORBA_Object_is_nil() */ captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL))
507                         return FALSE;
508                 }
509         if (corba_object_want!=CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ANY) {
510 CORBA_Object corba_object;
511
512                 corba_object=captive_parent_connector_get_corba_object(captive_parent_connector);
513                 g_assert(!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_BROKEN))
514                                 || corba_object==CORBA_OBJECT_NIL);
515                 if ((corba_object_want==CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ON)!=
516                                 (/* !CORBA_Object_is_nil() */ corba_object!=CORBA_OBJECT_NIL))
517                         return FALSE;
518                 }
519         if (dirty_want!=CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ANY) {
520 gboolean dirty;
521
522                 dirty=captive_parent_connector_get_dirty(captive_parent_connector);
523                 g_assert(!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_BROKEN))
524                                 || dirty==TRUE);
525                 if ((dirty_want==CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ON)!=dirty)
526                         return FALSE;
527                 }
528
529         return TRUE;
530 }