privbcb_set(): Forbid reincarnation of 'leave_func_pending' privbcb.
authorshort <>
Sun, 13 Jul 2003 09:27:04 +0000 (09:27 +0000)
committershort <>
Sun, 13 Jul 2003 09:27:04 +0000 (09:27 +0000)
captive_cc_flush(): Flush by g_tree first to attempt to keep LSN ordering.
CcUnpinData_leave_func(): Flush mode if privbcb_stop_at==NULL.
CcUnpinData_leave_func(): Flush only the requested privbcb by CcUnpinData().

src/libcaptive/cc/map.c

index fca7b5d..8676546 100644 (file)
@@ -391,8 +391,16 @@ static void privbcb_set(struct private_bcb *privbcb,enum privbcb_item item,gint
                case PRIVBCB_ITEM_LEAVE_FUNC_PENDING:
                        g_assert(TRUE==value || FALSE==value);
                        privbcb->leave_func_pending=value;
+                       if (value)
+                               g_assert(privbcb->ref_count==1);
                        break;
                case PRIVBCB_ITEM_REF_COUNT:
+                       /* Forbid reincarnation of 'leave_func_pending' privbcb.
+                        * Allow some of its 'ref_count' handling to properly clean it up.
+                        */
+                       if (privbcb->leave_func_pending)
+                               g_assert((privbcb->ref_count==1 && value==-1)
+                                     || (privbcb->ref_count==0 && value==+1));
                        g_assert(privbcb->ref_count>=0);
                        privbcb->ref_count+=value;
                        g_assert(privbcb->ref_count>=0);
@@ -603,6 +611,8 @@ static void captive_cc_flush_private_bcb_hash_foreach(
        captive_privbcb_flush(privbcb);
 }
 
+static void CcUnpinData_leave_func(struct private_bcb *privbcb_stop_at);
+
 void captive_cc_flush(void)
 {
 gboolean flushed;
@@ -611,6 +621,8 @@ gboolean flushed;
        private_bcb_hash_init();
 
        do {
+               /* Trace it by g_tree first to attempt to keep LSN ordering */
+               CcUnpinData_leave_func(NULL);
                flushed=FALSE;
                g_hash_table_foreach(
                                private_bcb_hash,       /* hash_table */
@@ -1307,14 +1319,14 @@ static gboolean CcUnpinData_leave_func_foreach_get_first(struct private_bcb *key
        return TRUE;    /* stop the traversal */
 }
 
-static void CcUnpinData_leave_func(gpointer user_data /* unused */)
+static void CcUnpinData_leave_func(struct private_bcb *privbcb_stop_at)        /* NULL to traverse the whole tree */
 {
 struct private_bcb *privbcb;
 gboolean errbool;
 
        private_bcb_flush_tree_init();
 
-       for (;;) {
+       do {
                privbcb=NULL;
                g_tree_foreach(private_bcb_flush_tree,
                                (GTraverseFunc)CcUnpinData_leave_func_foreach_get_first,        /* func */
@@ -1329,15 +1341,22 @@ gboolean errbool;
                                privbcb->FileObject,(guint64)privbcb->MappedFileOffset.QuadPart,(gulong)privbcb->MappedLength,(int)privbcb->ref_count,
                                (int)privbcb->leave_func_pending);
 
-               if (!privbcb->leave_func_pending) {
+               /* Do not stop at not yet modified buffers if not privbcb_stop_at==NULL,
+                * privbcb_stop_at==NULL is used to flush the whole cache.
+                */
+               if (privbcb_stop_at && !privbcb->leave_func_pending) {
                        g_assert(privbcb->lsn_valid);   /* cannout skip LSN-valid BCB */
                        break;
                        }
 
-               g_assert(privbcb->leave_func_pending==TRUE);
+               g_assert(!privbcb_stop_at || privbcb->leave_func_pending==TRUE);
                privbcb_set(privbcb,PRIVBCB_ITEM_LEAVE_FUNC_PENDING,FALSE);
                privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,-1);
-               if (privbcb->ref_count) {
+
+               /* Do not flush modified buffers if not privbcb_stop_at==NULL,
+                * privbcb_stop_at==NULL is used to flush the whole cache.
+                */
+               if (privbcb_stop_at && privbcb->ref_count) {
                        if (privbcb->lsn_valid) /* cannout skip LSN-valid BCB */
                                break;
                        continue;
@@ -1351,13 +1370,19 @@ gboolean errbool;
                        continue;
                        }
 
+               /* Clear it out of 'private_bcb_flush_tree' during global buffers flush. */
+               if (!privbcb_stop_at) {
+                       privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,-privbcb->ref_count);
+                       privbcb_set(privbcb,PRIVBCB_ITEM_LSN_VALID,FALSE);
+                       }
+
                g_assert(privbcb->leave_func_pending==FALSE);
                g_assert(privbcb->ref_count==0);
                g_assert(NULL==g_tree_lookup(private_bcb_flush_tree,privbcb));
 
                errbool=g_hash_table_remove(private_bcb_hash,privbcb->PublicBcb);
                g_assert(errbool==TRUE);
-               }
+               } while (!privbcb_stop_at || privbcb!=privbcb_stop_at);
 }
 
 /**
@@ -1409,7 +1434,7 @@ struct private_bcb *privbcb;
                privbcb_set(privbcb,PRIVBCB_ITEM_LEAVE_FUNC_PENDING,TRUE);
                captive_leave_register(
                                (captive_leave_func)CcUnpinData_leave_func,     /* func */
-                               privbcb);       /* data; unused */
+                               privbcb);       /* data; privbcb_stop_at */
                }
 
        if (captive_cc_unmounting)