2 * reactos Cache Manager (Cc*) SharedCacheMap structure of libcaptive
3 * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
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
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.
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
22 #include "sharedcachemap.h" /* self */
23 #include "sharedcachemap-priv.h" /* self */
25 #include "marshallers.h"
26 #include <glib-object.h>
27 #include "privatebcbpin.h"
28 #include "captive/macros.h"
34 #define ALLOCATION_BLOCK_SIZE 0x200
37 static GHashTable *CaptiveSharedCacheMapObject_hash;
39 static void CaptiveSharedCacheMapObject_hash_init(void)
41 if (CaptiveSharedCacheMapObject_hash)
43 CaptiveSharedCacheMapObject_hash=g_hash_table_new(
44 g_direct_hash, /* hash_func */
45 g_direct_equal); /* key_equal_func */
49 static gpointer captive_shared_cache_map_object_parent_class=NULL;
52 static void captive_shared_cache_map_object_finalize(CaptiveSharedCacheMapObject *captive_shared_cache_map_object)
54 static const CC_FILE_SIZES FileSizes_zero;
57 CaptiveSharedCacheMapObject_page *page;
59 g_return_if_fail(captive_shared_cache_map_object!=NULL);
61 for (offset=0;offset<CAPTIVE_ROUND_UP64(captive_shared_cache_map_object->AllocationSize,PAGE_SIZE);offset+=PAGE_SIZE) {
62 page=captive_shared_cache_map_object->pages+offset/PAGE_SIZE;
63 if (!page->data_valid)
65 g_assert(!page->dirty); /* FIXME: Is it allowed by W32? */
68 CaptiveSharedCacheMapObject_hash_init();
69 errbool=g_hash_table_remove(CaptiveSharedCacheMapObject_hash,captive_shared_cache_map_object);
70 g_assert(errbool==TRUE);
72 captive_shared_cache_map_FileSizes_set(captive_shared_cache_map_object,&FileSizes_zero);
73 g_assert(captive_shared_cache_map_object->buffer==NULL);
74 g_assert(captive_shared_cache_map_object->pages==NULL);
76 if (captive_shared_cache_map_object->pin_hash) {
77 captive_private_bcb_pin_object_hash_destroy(captive_shared_cache_map_object->pin_hash);
78 captive_shared_cache_map_object->pin_hash=NULL;
80 g_assert(captive_shared_cache_map_object->map==NULL);
81 if (captive_shared_cache_map_object->SectionObjectPointers) {
82 g_assert(captive_shared_cache_map_object==captive_shared_cache_map_object->SectionObjectPointers->SharedCacheMap);
83 captive_shared_cache_map_object->SectionObjectPointers->SharedCacheMap=NULL;
86 G_OBJECT_CLASS(captive_shared_cache_map_object_parent_class)->finalize((GObject *)captive_shared_cache_map_object);
89 static guint FileSizes_changed_signal;
90 static guint purge_signal;
92 static void captive_shared_cache_map_object_FileSizes_changed(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
93 guint64 AllocationSize,guint64 FileSize,guint64 ValidDataLength);
94 static void captive_shared_cache_map_object_purge(CaptiveSharedCacheMapObject *captive_shared_cache_map_object);
96 static void captive_shared_cache_map_object_class_init(CaptiveSharedCacheMapObjectClass *class)
98 GObjectClass *gobject_class=G_OBJECT_CLASS(class);
100 captive_shared_cache_map_object_parent_class=g_type_class_ref(G_TYPE_OBJECT);
101 gobject_class->finalize=(void (*)(GObject *object))captive_shared_cache_map_object_finalize;
103 class->FileSizes_changed=captive_shared_cache_map_object_FileSizes_changed;
104 class->purge=captive_shared_cache_map_object_purge;
106 FileSizes_changed_signal=g_signal_new("FileSizes_changed",
107 G_TYPE_FROM_CLASS(gobject_class),
109 G_STRUCT_OFFSET(CaptiveSharedCacheMapObjectClass,FileSizes_changed),
111 captive_cc_VOID__UINT64_UINT64_UINT64,
112 G_TYPE_NONE,3,G_TYPE_UINT64,G_TYPE_UINT64,G_TYPE_UINT64);
113 purge_signal=g_signal_new("purge",
114 G_TYPE_FROM_CLASS(gobject_class),
116 G_STRUCT_OFFSET(CaptiveSharedCacheMapObjectClass,purge),
118 captive_cc_VOID__VOID,
123 static void captive_shared_cache_map_object_init(CaptiveSharedCacheMapObject *captive_shared_cache_map_object)
125 captive_shared_cache_map_object->pin_hash=captive_private_bcb_pin_object_hash_new();
127 captive_shared_cache_map_w32_ref(captive_shared_cache_map_object);
128 g_object_unref(captive_shared_cache_map_object); /* ==sink */
130 CaptiveSharedCacheMapObject_hash_init();
131 g_hash_table_insert(CaptiveSharedCacheMapObject_hash,
132 captive_shared_cache_map_object,captive_shared_cache_map_object);
136 GType captive_shared_cache_map_object_get_type(void)
138 static GType captive_shared_cache_map_object_type=0;
140 if (!captive_shared_cache_map_object_type) {
141 static const GTypeInfo captive_shared_cache_map_object_info={
142 sizeof(CaptiveSharedCacheMapObjectClass),
143 NULL, /* base_init */
144 NULL, /* base_finalize */
145 (GClassInitFunc)captive_shared_cache_map_object_class_init,
146 NULL, /* class_finalize */
147 NULL, /* class_data */
148 sizeof(CaptiveSharedCacheMapObject),
150 (GInstanceInitFunc)captive_shared_cache_map_object_init,
153 captive_shared_cache_map_object_type=g_type_register_static(G_TYPE_OBJECT,
154 "CaptiveSharedCacheMapObject",&captive_shared_cache_map_object_info,0);
157 return captive_shared_cache_map_object_type;
160 static void captive_shared_cache_map_object_FileSizes_changed(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
161 guint64 AllocationSize,guint64 FileSize,guint64 ValidDataLength)
163 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
165 g_assert((!captive_shared_cache_map_object->buffer)==(!captive_shared_cache_map_object->AllocationSize));
166 g_assert((!captive_shared_cache_map_object->pages)==(!captive_shared_cache_map_object->AllocationSize));
168 if (captive_shared_cache_map_object->AllocationSize!=AllocationSize) {
169 size_t size_old,size_new;
170 guint64 size64_old,size64_new;
173 /* These two assertions should be already catched by pin/map signal handlers. */
174 g_assert(!captive_shared_cache_map_object->map);
175 g_assert(!g_hash_table_size(captive_shared_cache_map_object->pin_hash));
177 size64_old=CAPTIVE_ROUND_UP64(captive_shared_cache_map_object->AllocationSize,PAGE_SIZE);
179 g_assert(size_old==size64_old);
180 size64_new=CAPTIVE_ROUND_UP64(AllocationSize,PAGE_SIZE);
182 g_assert(size_new==size64_new);
184 if (AllocationSize) {
190 PAGE_SIZE+size_new+PAGE_SIZE, /* length; leading and trailing boundary check pages */
191 PROT_READ|PROT_WRITE, /* prot; read/write must be possible although write is not guaranteed to be flushed yet */
192 MAP_PRIVATE|MAP_ANONYMOUS, /* flags */
193 -1, /* fd; ignored due to MAP_ANONYMOUS */
194 0); /* offset; ignored due to MAP_ANONYMOUS */
195 g_assert(base!=NULL);
198 errint=munmap(base-PAGE_SIZE,PAGE_SIZE); /* unmap leading boundary check page */
200 errint=munmap(base+size_new,PAGE_SIZE); /* unmap trailing boundary check page */
205 memcpy(buffer_new,captive_shared_cache_map_object->buffer,
206 MIN(AllocationSize,captive_shared_cache_map_object->AllocationSize));
207 if (captive_shared_cache_map_object->AllocationSize) {
210 errint=munmap(captive_shared_cache_map_object->buffer,size_old);
213 captive_shared_cache_map_object->buffer=buffer_new;
215 captive_shared_cache_map_object->pages=g_realloc(captive_shared_cache_map_object->pages,
216 size_new/PAGE_SIZE*sizeof(*captive_shared_cache_map_object->pages));
217 memset(captive_shared_cache_map_object->pages+(size_old/PAGE_SIZE),0,
218 MAX(0,size_new-size_old)/PAGE_SIZE*sizeof(*captive_shared_cache_map_object->pages));
221 captive_shared_cache_map_object->AllocationSize=AllocationSize;
222 captive_shared_cache_map_object->FileSize=FileSize;
223 captive_shared_cache_map_object->ValidDataLength=ValidDataLength;
225 g_assert((!captive_shared_cache_map_object->buffer)==(!captive_shared_cache_map_object->AllocationSize));
226 g_assert((!captive_shared_cache_map_object->pages)==(!captive_shared_cache_map_object->AllocationSize));
229 static void captive_shared_cache_map_object_purge(CaptiveSharedCacheMapObject *captive_shared_cache_map_object)
231 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
233 /* NOP; just to provide slot for checking by Bcbs */
236 CaptiveSharedCacheMapObject *captive_shared_cache_map_get_ref(FILE_OBJECT *FileObject,
237 const CC_FILE_SIZES *FileSizes,BOOLEAN PinAccess,CACHE_MANAGER_CALLBACKS *CallBacks,VOID *LazyWriterContext)
239 CaptiveSharedCacheMapObject *captive_shared_cache_map_object;
241 g_return_val_if_fail(FileObject!=NULL,NULL);
242 g_return_val_if_fail(FileObject->SectionObjectPointers!=NULL,NULL);
243 g_return_val_if_fail(FileSizes!=NULL,NULL);
244 g_return_val_if_fail(CallBacks!=NULL,NULL);
246 if ((captive_shared_cache_map_object=FileObject->SectionObjectPointers->SharedCacheMap)) {
247 captive_shared_cache_map_w32_ref(captive_shared_cache_map_object);
250 captive_shared_cache_map_object=g_object_new(
251 CAPTIVE_SHARED_CACHE_MAP_TYPE_OBJECT, /* object_type */
252 NULL); /* first_property_name; FIXME: support properties */
254 captive_shared_cache_map_object->FileObject=FileObject;
255 captive_shared_cache_map_object->SectionObjectPointers=FileObject->SectionObjectPointers;
256 captive_shared_cache_map_object->AllocationSize=0;
257 captive_shared_cache_map_object->FileSize=0;
258 captive_shared_cache_map_object->ValidDataLength=0;
259 captive_shared_cache_map_object->PinAccess=PinAccess;
260 captive_shared_cache_map_object->CallBacks=*CallBacks;
261 captive_shared_cache_map_object->LazyWriterContext=LazyWriterContext;
263 FileObject->SectionObjectPointers->SharedCacheMap=captive_shared_cache_map_object;
266 g_assert(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
267 /* FileObject may differ - we can have a different reference to the same FCB. */
268 g_assert(FileObject->SectionObjectPointers==captive_shared_cache_map_object->SectionObjectPointers);
269 g_assert(PinAccess==captive_shared_cache_map_object->PinAccess);
270 g_assert(CallBacks->AcquireForLazyWrite==captive_shared_cache_map_object->CallBacks.AcquireForLazyWrite);
271 g_assert(CallBacks->ReleaseFromLazyWrite==captive_shared_cache_map_object->CallBacks.ReleaseFromLazyWrite);
272 g_assert(CallBacks->AcquireForReadAhead==captive_shared_cache_map_object->CallBacks.AcquireForReadAhead);
273 g_assert(CallBacks->ReleaseFromReadAhead==captive_shared_cache_map_object->CallBacks.ReleaseFromReadAhead);
274 g_assert(LazyWriterContext==captive_shared_cache_map_object->LazyWriterContext);
276 captive_shared_cache_map_FileSizes_set(captive_shared_cache_map_object,FileSizes);
278 return captive_shared_cache_map_object;
281 void captive_shared_cache_map_FileSizes_set(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
282 const CC_FILE_SIZES *FileSizes)
284 guint64 AllocationSize,FileSize,ValidDataLength;
286 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
287 g_return_if_fail(FileSizes!=NULL);
289 AllocationSize=FileSizes->AllocationSize.QuadPart;
290 FileSize=FileSizes->FileSize.QuadPart;
291 ValidDataLength=FileSizes->ValidDataLength.QuadPart;
293 if (ValidDataLength==G_MAXINT64)
294 ValidDataLength=FileSize;
296 g_assert(AllocationSize>=0);
297 g_assert(FileSize>=0);
298 g_assert(ValidDataLength>=0);
300 g_assert(ValidDataLength<=FileSize);
301 g_assert(0==(AllocationSize%ALLOCATION_BLOCK_SIZE));
302 /* AllocationSize can be much higher: */
303 g_assert(FileSize<=AllocationSize);
305 g_signal_emit(captive_shared_cache_map_object,FileSizes_changed_signal,0,
306 AllocationSize,FileSize,ValidDataLength);
308 g_assert(captive_shared_cache_map_object->AllocationSize==AllocationSize);
309 g_assert(captive_shared_cache_map_object->FileSize==FileSize);
310 g_assert(captive_shared_cache_map_object->ValidDataLength==ValidDataLength);
313 CaptiveSharedCacheMapObject *captive_SectionObjectPointers_to_SharedCacheMap(SECTION_OBJECT_POINTERS *SectionObjectPointers)
315 g_return_val_if_fail(SectionObjectPointers!=NULL,NULL);
316 g_return_val_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(SectionObjectPointers->SharedCacheMap),NULL);
318 return SectionObjectPointers->SharedCacheMap;
321 CaptiveSharedCacheMapObject *captive_FileObject_to_SharedCacheMap(FILE_OBJECT *FileObject)
323 g_return_val_if_fail(FileObject!=NULL,NULL);
325 return captive_SectionObjectPointers_to_SharedCacheMap(FileObject->SectionObjectPointers);
328 void captive_shared_cache_map_w32_ref(CaptiveSharedCacheMapObject *captive_shared_cache_map_object)
330 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
332 g_object_ref(captive_shared_cache_map_object);
333 captive_shared_cache_map_object->w32_ref_count++;
336 void captive_shared_cache_map_w32_unref(CaptiveSharedCacheMapObject *captive_shared_cache_map_object)
338 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
339 g_return_if_fail(G_OBJECT(captive_shared_cache_map_object)->ref_count>0);
341 captive_shared_cache_map_object->w32_ref_count--;
342 if (!captive_shared_cache_map_object->w32_ref_count)
343 g_assert(G_OBJECT(captive_shared_cache_map_object)->ref_count==1);
345 g_object_unref(captive_shared_cache_map_object);
348 void captive_shared_cache_map_data_validate_read(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
349 FILE_OBJECT *FileObject,guint64 start,guint64 end)
352 gboolean after_eof=FALSE; /* Did we reached the end of file already? */
354 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
355 g_return_if_fail(captive_shared_cache_map_object==captive_FileObject_to_SharedCacheMap(FileObject));
356 g_return_if_fail(start<=end);
357 g_return_if_fail(end<=captive_shared_cache_map_object->ValidDataLength);
359 start=CAPTIVE_ROUND_DOWN64(start,PAGE_SIZE);
360 end=CAPTIVE_ROUND_UP64(end,PAGE_SIZE);
362 for (now=start;now<end;now+=PAGE_SIZE) {
363 LARGE_INTEGER now_LargeInteger;
366 if (captive_shared_cache_map_object->pages[now/PAGE_SIZE].data_valid)
368 now_LargeInteger.QuadPart=now;
369 got=captive_Cc_IoPageRead(FileObject,captive_shared_cache_map_object->buffer+now,PAGE_SIZE,&now_LargeInteger);
373 g_assert(got<=PAGE_SIZE);
374 after_eof=(got<PAGE_SIZE);
375 captive_shared_cache_map_object->pages[now/PAGE_SIZE].data_valid=TRUE;
379 void captive_shared_cache_map_data_validate_noread(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
380 guint64 start,guint64 end)
384 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
385 g_return_if_fail(start<=end);
386 g_return_if_fail(end<=captive_shared_cache_map_object->ValidDataLength);
388 start=CAPTIVE_ROUND_DOWN64(start,PAGE_SIZE);
389 end=CAPTIVE_ROUND_UP64(end,PAGE_SIZE);
391 for (now=start;now<end;now+=PAGE_SIZE) {
392 g_assert(captive_shared_cache_map_object->pages[now/PAGE_SIZE].data_valid);
396 void captive_shared_cache_map_set_data_valid(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
397 guint64 start,guint64 end)
401 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
402 g_return_if_fail(start<=end);
403 g_return_if_fail(end<=captive_shared_cache_map_object->ValidDataLength);
405 start=CAPTIVE_ROUND_DOWN64(start,PAGE_SIZE);
406 end=CAPTIVE_ROUND_UP64(end,PAGE_SIZE);
408 for (now=start;now<end;now+=PAGE_SIZE) {
409 captive_shared_cache_map_object->pages[now/PAGE_SIZE].data_valid=TRUE;
413 void captive_shared_cache_map_set_dirty(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
414 guint64 start,guint64 end)
417 CaptiveSharedCacheMapObject_page *page;
419 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
420 g_return_if_fail(end<=captive_shared_cache_map_object->ValidDataLength);
422 start=CAPTIVE_ROUND_DOWN64(start,PAGE_SIZE);
423 end=CAPTIVE_ROUND_UP64(end,PAGE_SIZE);
425 for (now=start;now<end;now+=PAGE_SIZE) {
426 page=captive_shared_cache_map_object->pages+now/PAGE_SIZE;
427 g_assert(page->data_valid);
436 gboolean captive_shared_cache_map_is_page_dirty(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
439 CaptiveSharedCacheMapObject_page *page;
441 g_return_val_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object),FALSE);
442 g_return_val_if_fail(offset<captive_shared_cache_map_object->ValidDataLength,FALSE);
443 g_return_val_if_fail(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(offset,PAGE_SIZE),FALSE);
444 page=captive_shared_cache_map_object->pages+offset/PAGE_SIZE;
445 g_return_val_if_fail(page->data_valid,FALSE);
450 void captive_shared_cache_map_page_set_lsn(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
451 guint64 offset,gint64 lsn)
453 CaptiveSharedCacheMapObject_page *page;
455 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
456 g_return_if_fail(offset<captive_shared_cache_map_object->ValidDataLength);
457 g_return_if_fail(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(offset,PAGE_SIZE));
458 page=captive_shared_cache_map_object->pages+offset/PAGE_SIZE;
459 g_return_if_fail(page->data_valid);
460 g_return_if_fail(page->dirty);
461 g_return_if_fail(page->lsn_oldest<=page->lsn_newest);
462 g_return_if_fail(!page->lsn_newest || lsn>=page->lsn_newest);
463 g_return_if_fail(captive_shared_cache_map_object->LogHandle_set);
464 g_return_if_fail(captive_shared_cache_map_object->FlushToLsnRoutine_set);
466 if (!page->lsn_oldest)
467 page->lsn_oldest=lsn;
468 page->lsn_newest=lsn;
471 void captive_shared_cache_map_purge(CaptiveSharedCacheMapObject *captive_shared_cache_map_object)
474 CaptiveSharedCacheMapObject_page *page;
476 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
478 g_signal_emit(captive_shared_cache_map_object,purge_signal,0);
480 for (offset=0;offset<CAPTIVE_ROUND_UP64(captive_shared_cache_map_object->AllocationSize,PAGE_SIZE);offset+=PAGE_SIZE) {
481 page=captive_shared_cache_map_object->pages+offset/PAGE_SIZE;
482 if (!page->data_valid)
484 g_assert(!page->dirty); /* FIXME: Is it allowed by W32? */
485 page->data_valid=FALSE;
489 static VOID *captive_LogHandle;
490 static PFLUSH_TO_LSN captive_FlushToLsnRoutine;
492 void captive_shared_cache_map_set_LogHandle(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,VOID *LogHandle)
494 g_return_if_fail(!captive_shared_cache_map_object || CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
495 g_return_if_fail(!captive_shared_cache_map_object || !captive_shared_cache_map_object->LogHandle_set);
499 g_assert(!captive_LogHandle || captive_LogHandle==LogHandle);
500 captive_LogHandle=LogHandle;
501 if (LogHandle && captive_shared_cache_map_object)
502 captive_shared_cache_map_object->LogHandle_set=TRUE;
505 void captive_shared_cache_map_set_FlushToLsnRoutine
506 (CaptiveSharedCacheMapObject *captive_shared_cache_map_object,PFLUSH_TO_LSN FlushToLsnRoutine)
508 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
509 g_return_if_fail(!captive_shared_cache_map_object->FlushToLsnRoutine_set);
511 if (!FlushToLsnRoutine)
513 g_assert(!captive_FlushToLsnRoutine || captive_FlushToLsnRoutine==FlushToLsnRoutine);
514 captive_FlushToLsnRoutine=FlushToLsnRoutine;
515 if (FlushToLsnRoutine)
516 captive_shared_cache_map_object->FlushToLsnRoutine_set=TRUE;
519 static void captive_shared_cache_map_page_write(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
522 LARGE_INTEGER offset_LargeInteger;
523 static gint64 lsn_last;
524 CaptiveSharedCacheMapObject_page *page;
526 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
527 g_return_if_fail(offset<captive_shared_cache_map_object->ValidDataLength);
528 g_return_if_fail(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(offset,PAGE_SIZE));
529 page=captive_shared_cache_map_object->pages+offset/PAGE_SIZE;
530 g_return_if_fail(page->data_valid);
531 g_return_if_fail(page->dirty);
533 if (page->lsn_newest) {
534 LARGE_INTEGER lsn_newest_LargeInteger;
537 g_assert(!lsn_last || lsn_last<=page->lsn_newest);
538 lsn_last=page->lsn_newest;
540 lsn_newest_LargeInteger.QuadPart=page->lsn_newest;
541 (*captive_FlushToLsnRoutine)(captive_LogHandle,lsn_newest_LargeInteger);
544 offset_LargeInteger.QuadPart=offset;
545 captive_Cc_IoPageWrite(captive_shared_cache_map_object->FileObject,
546 captive_shared_cache_map_object->buffer+offset,PAGE_SIZE,&offset_LargeInteger);
553 guint64 captive_shared_cache_map_flush(CaptiveSharedCacheMapObject *captive_shared_cache_map_object,
554 guint64 start,guint64 end)
559 g_return_val_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object),0);
560 g_return_val_if_fail(start<=end,0);
562 if (end>captive_shared_cache_map_object->ValidDataLength)
563 end=captive_shared_cache_map_object->ValidDataLength;
565 start=CAPTIVE_ROUND_DOWN64(start,PAGE_SIZE);
566 end=CAPTIVE_ROUND_UP64(end,PAGE_SIZE);
569 for (now=start;now<end;now+=PAGE_SIZE) {
570 if (!captive_shared_cache_map_object->pages[now/PAGE_SIZE].data_valid)
572 if (!captive_shared_cache_map_object->pages[now/PAGE_SIZE].dirty)
574 captive_shared_cache_map_page_write(captive_shared_cache_map_object,now);
578 /* We were calling W32 code - recheck our task completion. */
579 for (now=start;now<end;now+=PAGE_SIZE) {
580 if (!captive_shared_cache_map_object->pages[now/PAGE_SIZE].data_valid)
582 g_assert(!captive_shared_cache_map_object->pages[now/PAGE_SIZE].dirty);
588 static void captive_shared_cache_map_is_any_dirty_foreach(
589 CaptiveSharedCacheMapObject *captive_shared_cache_map_object, /* key */
590 CaptiveSharedCacheMapObject *captive_shared_cache_map_object_value, /* value */
591 gboolean *dirty_foundp) /* user_data */
595 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
596 g_return_if_fail(captive_shared_cache_map_object==captive_shared_cache_map_object_value);
597 g_return_if_fail(dirty_foundp!=NULL);
599 for (now=0;now<captive_shared_cache_map_object->AllocationSize;now+=PAGE_SIZE) {
600 if (!captive_shared_cache_map_object->pages[now/PAGE_SIZE].data_valid)
602 if (!captive_shared_cache_map_object->pages[now/PAGE_SIZE].dirty)
604 *dirty_foundp=TRUE; /* FIXME: stop the traversal. */
610 gboolean captive_shared_cache_map_is_any_dirty(void)
612 gboolean dirty_found;
614 CaptiveSharedCacheMapObject_hash_init();
616 g_hash_table_foreach(
617 CaptiveSharedCacheMapObject_hash, /* hash_table */
618 (GHFunc)captive_shared_cache_map_is_any_dirty_foreach, /* func */
619 &dirty_found); /* user_data */
625 typedef struct _captive_shared_cache_map_CcGetDirtyPages_foreach_param captive_shared_cache_map_CcGetDirtyPages_foreach_param;
626 struct _captive_shared_cache_map_CcGetDirtyPages_foreach_param {
627 PDIRTY_PAGE_ROUTINE DirtyPageRoutine;
633 static void captive_shared_cache_map_CcGetDirtyPages_foreach(
634 CaptiveSharedCacheMapObject *captive_shared_cache_map_object, /* key */
635 CaptiveSharedCacheMapObject *captive_shared_cache_map_object_value, /* value */
636 captive_shared_cache_map_CcGetDirtyPages_foreach_param *param) /* user_data */
639 CaptiveSharedCacheMapObject_page *page;
641 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
642 g_return_if_fail(captive_shared_cache_map_object==captive_shared_cache_map_object_value);
643 g_return_if_fail(param!=NULL);
645 for (now=CAPTIVE_ROUND_DOWN64(captive_shared_cache_map_object->AllocationSize-1,PAGE_SIZE);now>=0;now-=PAGE_SIZE) {
646 LARGE_INTEGER now_LargeInteger,lsn_oldest_LargeInteger,lsn_newest_LargeInteger;
648 page=captive_shared_cache_map_object->pages+now/PAGE_SIZE;
649 if (!page->data_valid)
653 if (page->lsn_oldest && (!param->result || param->result>page->lsn_oldest))
654 param->result=page->lsn_oldest;
656 now_LargeInteger.QuadPart=now;
657 lsn_oldest_LargeInteger.QuadPart=page->lsn_oldest;
658 lsn_newest_LargeInteger.QuadPart=page->lsn_newest;
659 (*param->DirtyPageRoutine)(
660 captive_shared_cache_map_object->FileObject, /* FileObject */
661 &now_LargeInteger, /* FileOffset */
662 PAGE_SIZE, /* Length */
663 &lsn_oldest_LargeInteger, /* OldestLsn */
664 &lsn_newest_LargeInteger, /* NewestLsn */
665 param->Context1, /* Context1 */
666 param->Context2); /* Context2 */
670 gint64 captive_shared_cache_map_CcGetDirtyPages(PDIRTY_PAGE_ROUTINE DirtyPageRoutine,VOID *Context1,VOID *Context2)
672 captive_shared_cache_map_CcGetDirtyPages_foreach_param param;
674 g_return_val_if_fail(DirtyPageRoutine!=NULL,0);
676 param.DirtyPageRoutine=DirtyPageRoutine;
677 param.Context1=Context1;
678 param.Context2=Context2;
681 CaptiveSharedCacheMapObject_hash_init();
682 g_hash_table_foreach(
683 CaptiveSharedCacheMapObject_hash, /* hash_table */
684 (GHFunc)captive_shared_cache_map_CcGetDirtyPages_foreach, /* func */
685 ¶m); /* user_data */
690 gpointer captive_shared_cache_map_get_buffer(CaptiveSharedCacheMapObject *captive_shared_cache_map_object)
692 g_return_val_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object),NULL);
693 g_return_val_if_fail(captive_shared_cache_map_object->buffer!=NULL,NULL);
695 return captive_shared_cache_map_object->buffer;
698 static void captive_cc_FileObject_delete_foreach(
699 CaptiveSharedCacheMapObject *captive_shared_cache_map_object, /* key */
700 CaptiveSharedCacheMapObject *captive_shared_cache_map_object_value, /* value */
701 FILE_OBJECT *FileObject) /* user_data */
703 g_return_if_fail(CAPTIVE_SHARED_CACHE_MAP_IS_OBJECT(captive_shared_cache_map_object));
704 g_return_if_fail(captive_shared_cache_map_object==captive_shared_cache_map_object_value);
705 g_return_if_fail(FileObject!=NULL);
707 g_assert(FileObject!=captive_shared_cache_map_object->FileObject);
710 BOOLEAN captive_cc_FileObject_delete(FILE_OBJECT *FileObject)
712 g_return_val_if_fail(FileObject!=NULL,FALSE);
714 CaptiveSharedCacheMapObject_hash_init();
715 g_hash_table_foreach(
716 CaptiveSharedCacheMapObject_hash, /* hash_table */
717 (GHFunc)captive_cc_FileObject_delete_foreach, /* func */
718 FileObject); /* user_data */
720 return FALSE; /* FIXME: remove useless return code. */