Replaced all 'FileSize' sanity checks for more relaxed 'AllocationSize' checks.
[captive.git] / src / libcaptive / cc / privatebcbpin.c
1 /* $Id$
2  * reactos Cache Manager (Cc*) PrivateBcb Map type structure of libcaptive
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 "privatebcbpin.h"      /* self */
23 #include "privatebcb.h"
24 #include "privatebcb-priv.h"
25 #include "sharedcachemap-priv.h"
26 #include <glib-object.h>
27 #include "captive/macros.h"
28
29
30 struct _CaptivePrivateBcbPinObject {
31         CaptivePrivateBcbObject parent_instance;
32
33         gulong FileSizes_changed_handler_id;
34         gulong FileSizes_changed_after_handler_id;
35         gulong purge_handler_id;
36         guint64 offset;
37         };
38 struct _CaptivePrivateBcbPinObjectClass {
39         CaptivePrivateBcbObjectClass parent_class;
40         };
41
42
43 static gpointer captive_private_bcb_pin_object_parent_class=NULL;
44
45
46 static void captive_private_bcb_pin_object_finalize(CaptivePrivateBcbPinObject *captive_private_bcb_pin_object)
47 {
48 CaptivePrivateBcbObject *captive_private_bcb_object;
49 CaptiveSharedCacheMapObject *SharedCacheMap;
50 GHashTable *pin_hash;
51
52         g_return_if_fail(captive_private_bcb_pin_object!=NULL);
53
54         captive_private_bcb_object=CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object);
55
56         if (captive_private_bcb_pin_object->FileSizes_changed_handler_id) {
57                 g_assert(captive_private_bcb_object->SharedCacheMap!=NULL);
58                 g_signal_handler_disconnect(
59                                 captive_private_bcb_object->SharedCacheMap,     /* instance */
60                                 captive_private_bcb_pin_object->FileSizes_changed_handler_id);
61                 captive_private_bcb_pin_object->FileSizes_changed_handler_id=0;
62                 }
63         if (captive_private_bcb_pin_object->FileSizes_changed_after_handler_id) {
64                 g_assert(captive_private_bcb_object->SharedCacheMap!=NULL);
65                 g_signal_handler_disconnect(
66                                 captive_private_bcb_object->SharedCacheMap,     /* instance */
67                                 captive_private_bcb_pin_object->FileSizes_changed_after_handler_id);
68                 captive_private_bcb_pin_object->FileSizes_changed_after_handler_id=0;
69                 }
70         if (captive_private_bcb_pin_object->purge_handler_id) {
71                 g_assert(captive_private_bcb_object->SharedCacheMap!=NULL);
72                 g_signal_handler_disconnect(
73                                 captive_private_bcb_object->SharedCacheMap,     /* instance */
74                                 captive_private_bcb_pin_object->purge_handler_id);
75                 captive_private_bcb_pin_object->purge_handler_id=0;
76                 }
77         if ((SharedCacheMap=captive_private_bcb_object->SharedCacheMap)) {
78                 if ((pin_hash=SharedCacheMap->pin_hash)) {
79                         /* Do not: g_assert(g_hash_table_lookup(pin_hash,&captive_private_bcb_object->offset));
80                          * as we may be captive_private_bcb_pin_object_detach_pin()ed.
81                          */
82                         if (captive_private_bcb_object==g_hash_table_lookup(pin_hash,&captive_private_bcb_pin_object->offset))
83                                 g_hash_table_remove(pin_hash,&captive_private_bcb_pin_object->offset);
84                         }
85                 }
86
87         G_OBJECT_CLASS(captive_private_bcb_pin_object_parent_class)->finalize((GObject *)captive_private_bcb_pin_object);
88 }
89
90
91 static void captive_private_bcb_pin_object_class_init(CaptivePrivateBcbPinObjectClass *class)
92 {
93 GObjectClass *gobject_class=G_OBJECT_CLASS(class);
94
95         captive_private_bcb_pin_object_parent_class=g_type_class_ref(G_TYPE_OBJECT);
96         gobject_class->finalize=(void (*)(GObject *object))captive_private_bcb_pin_object_finalize;
97 }
98
99 static void captive_private_bcb_pin_object_init(CaptivePrivateBcbPinObject *captive_private_bcb_pin_object)
100 {
101 }
102
103 GType captive_private_bcb_pin_object_get_type(void)
104 {
105 static GType captive_private_bcb_pin_object_type=0;
106
107         if (!captive_private_bcb_pin_object_type) {
108 static const GTypeInfo captive_private_bcb_pin_object_info={
109                                 sizeof(CaptivePrivateBcbPinObjectClass),
110                                 NULL,   /* base_init */
111                                 NULL,   /* base_finalize */
112                                 (GClassInitFunc)captive_private_bcb_pin_object_class_init,
113                                 NULL,   /* class_finalize */
114                                 NULL,   /* class_data */
115                                 sizeof(CaptivePrivateBcbPinObject),
116                                 5,      /* n_preallocs */
117                                 (GInstanceInitFunc)captive_private_bcb_pin_object_init,
118                                 };
119
120                 captive_private_bcb_pin_object_type=g_type_register_static(CAPTIVE_PRIVATE_BCB_TYPE_OBJECT,
121                                 "CaptivePrivateBcbPinObject",&captive_private_bcb_pin_object_info,0);
122                 }
123
124         return captive_private_bcb_pin_object_type;
125 }
126
127
128 static guint captive_private_bcb_pin_object_hash_new_hash_func(const guint64 *offsetp)
129 {
130         return (*offsetp)^((*offsetp)>>32);
131 }
132
133 static gboolean captive_private_bcb_pin_object_hash_new_key_compare_func(const guint64 *offset_ap,const guint64 *offset_bp)
134 {
135         return (*offset_ap)==(*offset_bp);
136 }
137
138 GHashTable *captive_private_bcb_pin_object_hash_new(void)
139 {
140         return g_hash_table_new(
141                         (GHashFunc)captive_private_bcb_pin_object_hash_new_hash_func,
142                         (GEqualFunc)captive_private_bcb_pin_object_hash_new_key_compare_func);
143 }
144
145 void captive_private_bcb_pin_object_hash_destroy(GHashTable *pin_hash)
146 {
147         g_return_if_fail(pin_hash!=NULL);
148
149         g_hash_table_destroy(pin_hash);
150 }
151
152 static void captive_private_bcb_pin_object_validate(CaptivePrivateBcbPinObject *captive_private_bcb_pin_object)
153 {
154 guint64 start,end;
155
156         g_return_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
157         g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(
158                         CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap));
159
160         start=captive_private_bcb_pin_object->offset;
161         end  =captive_private_bcb_pin_object->offset+PAGE_SIZE;
162
163         g_assert(end<=CAPTIVE_ROUND_UP64(
164                         CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap->AllocationSize,PAGE_SIZE));
165 }
166
167 static void captive_private_bcb_pin_object_FileSizes_changed(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
168                 guint64 AllocationSize,guint64 FileSize,guint64 ValidDataLength,
169                 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object /* user_data */)
170 {
171         g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
172         g_return_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
173         g_return_if_fail(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap
174                         ==captive_shared_cache_map_object);
175
176         /* 'AllocationSize' must not change if any map/pin Bcbs exist. */
177         g_assert(AllocationSize==captive_shared_cache_map_object->AllocationSize);
178 }
179
180 static void captive_private_bcb_pin_object_purge(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
181                 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object /* user_data */)
182 {
183         g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
184         g_return_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
185         g_return_if_fail(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap
186                         ==captive_shared_cache_map_object);
187
188         g_assert(!captive_shared_cache_map_is_page_dirty(captive_shared_cache_map_object,
189                         captive_private_bcb_pin_object->offset));
190 }
191
192 static void captive_private_bcb_pin_object_FileSizes_changed_after(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
193                 guint64 AllocationSize,guint64 FileSize,guint64 ValidDataLength,
194                 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object /* user_data */)
195 {
196         g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
197         g_return_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
198         g_return_if_fail(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap
199                         ==captive_shared_cache_map_object);
200
201         /* we are 'g_signal_connect_after' */
202         g_assert(AllocationSize ==captive_shared_cache_map_object->AllocationSize);
203         g_assert(FileSize       ==captive_shared_cache_map_object->FileSize);
204         g_assert(ValidDataLength==captive_shared_cache_map_object->ValidDataLength);
205
206         captive_private_bcb_pin_object_validate(captive_private_bcb_pin_object);
207 }
208
209 void _captive_private_bcb_pin_object_connect_SharedCacheMap
210                 (CaptivePrivateBcbPinObject *captive_private_bcb_pin_object,CaptiveSharedCacheMapObject *captive_shared_cache_map_object)
211 {
212         g_return_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
213         g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
214         g_return_if_fail(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap==NULL);
215
216         _captive_private_bcb_object_connect_SharedCacheMap(
217                         CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object),captive_shared_cache_map_object);
218
219         captive_private_bcb_pin_object->FileSizes_changed_handler_id=g_signal_connect(
220                         captive_shared_cache_map_object,"FileSizes_changed",
221                         G_CALLBACK(captive_private_bcb_pin_object_FileSizes_changed),
222                         captive_private_bcb_pin_object);
223         g_assert(captive_private_bcb_pin_object->FileSizes_changed_handler_id>=1);
224         captive_private_bcb_pin_object->FileSizes_changed_after_handler_id=g_signal_connect_after(
225                         captive_shared_cache_map_object,"FileSizes_changed",
226                         G_CALLBACK(captive_private_bcb_pin_object_FileSizes_changed_after),
227                         captive_private_bcb_pin_object);
228         g_assert(captive_private_bcb_pin_object->FileSizes_changed_after_handler_id>=1);
229         captive_private_bcb_pin_object->purge_handler_id=g_signal_connect(
230                         captive_shared_cache_map_object,"purge",
231                         G_CALLBACK(captive_private_bcb_pin_object_purge),
232                         captive_private_bcb_pin_object);
233         g_assert(captive_private_bcb_pin_object->purge_handler_id>=1);
234 }
235
236 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object_new(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
237                 guint64 offset)
238 {
239 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
240
241         g_return_val_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object),NULL);
242         g_return_val_if_fail(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(offset,PAGE_SIZE),NULL);
243
244         g_assert(captive_shared_cache_map_object->PinAccess);
245
246         captive_private_bcb_pin_object=g_object_new(
247                         CAPTIVE_PRIVATE_BCB_PIN_TYPE_OBJECT,    /* object_type */
248                         NULL);  /* first_property_name; FIXME: support properties */
249
250         captive_private_bcb_pin_object->offset=offset;
251
252         _captive_private_bcb_pin_object_connect_SharedCacheMap(captive_private_bcb_pin_object,
253                         captive_shared_cache_map_object);
254
255         g_assert(captive_shared_cache_map_object->pin_hash!=NULL);
256         g_assert(!g_hash_table_lookup(captive_shared_cache_map_object->pin_hash,
257                         &captive_private_bcb_pin_object->offset));
258         g_hash_table_insert(captive_shared_cache_map_object->pin_hash,
259                         &captive_private_bcb_pin_object->offset,
260                         captive_private_bcb_pin_object);
261
262         return captive_private_bcb_pin_object;
263 }
264
265 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object_get(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
266                 guint64 offset)
267 {
268 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
269
270         g_return_val_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object),NULL);
271         g_return_val_if_fail(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(offset,PAGE_SIZE),NULL);
272
273         if ((captive_private_bcb_pin_object=g_hash_table_lookup(captive_shared_cache_map_object->pin_hash,
274                         &offset))) {
275                 g_assert(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
276                 return captive_private_bcb_pin_object;
277                 }
278         return NULL;
279 }
280
281 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object_get_ref(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
282                 guint64 offset)
283 {
284 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
285
286         g_return_val_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object),NULL);
287         g_return_val_if_fail(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(offset,PAGE_SIZE),NULL);
288
289         if ((captive_private_bcb_pin_object=captive_private_bcb_pin_object_get(captive_shared_cache_map_object,offset))) {
290                 g_assert(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
291                 g_object_ref(captive_private_bcb_pin_object);
292                 return captive_private_bcb_pin_object;
293                 }
294         return captive_private_bcb_pin_object_new(captive_shared_cache_map_object,offset);
295 }
296
297 gboolean captive_private_bcb_pin_object_is_dirty(CaptivePrivateBcbPinObject *captive_private_bcb_pin_object)
298 {
299         g_return_val_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object),FALSE);
300         g_return_val_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(
301                         CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap),FALSE);
302
303         return captive_shared_cache_map_is_page_dirty(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap,
304                         captive_private_bcb_pin_object->offset);
305 }
306
307 void captive_private_bcb_pin_object_flush(CaptivePrivateBcbPinObject *captive_private_bcb_pin_object)
308 {
309         g_return_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
310         g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(
311                         CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap));
312         g_return_if_fail(captive_private_bcb_pin_object_is_dirty(captive_private_bcb_pin_object));
313
314         /* Flush synchronously here. */
315         captive_shared_cache_map_flush(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap,
316                         captive_private_bcb_pin_object->offset,
317                         captive_private_bcb_pin_object->offset+PAGE_SIZE);
318 }
319
320 void captive_private_bcb_pin_object_set_dirty(CaptivePrivateBcbPinObject *captive_private_bcb_pin_object)
321 {
322         g_return_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
323         g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(
324                         CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap));
325
326         captive_shared_cache_map_set_dirty(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap,
327                         captive_private_bcb_pin_object->offset,
328                         captive_private_bcb_pin_object->offset+PAGE_SIZE);
329 }
330
331 void captive_private_bcb_pin_object_set_lsn(CaptivePrivateBcbPinObject *captive_private_bcb_pin_object,gint64 lsn)
332 {
333         g_return_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
334         g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(
335                         CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap));
336
337         captive_shared_cache_map_page_set_lsn(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)->SharedCacheMap,
338                         captive_private_bcb_pin_object->offset,lsn);
339 }
340
341 void captive_private_bcb_pin_object_detach_pin(CaptivePrivateBcbPinObject *captive_private_bcb_pin_object)
342 {
343 CaptiveSharedCacheMapObject *SharedCacheMap;
344
345         g_return_if_fail(CAPTIVE_PRIVATE_BCB_PIN_IS_OBJECT(captive_private_bcb_pin_object));
346
347         SharedCacheMap=captive_private_bcb_object_get_SharedCacheMap(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object));
348         g_assert(SharedCacheMap->pin_hash!=NULL);
349         g_assert(captive_private_bcb_pin_object==g_hash_table_lookup(SharedCacheMap->pin_hash,
350                         &captive_private_bcb_pin_object->offset));
351         g_hash_table_remove(SharedCacheMap->pin_hash,&captive_private_bcb_pin_object->offset);
352 }