LCOV - code coverage report
Current view: top level - autotest/cpp - testblockcachewrite.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 83 85 97.6 %
Date: 2025-01-18 12:42:00 Functions: 13 14 92.9 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Test block cache & writing behaviour under multi-threading
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys dot com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_conv.h"
      14             : #include "cpl_multiproc.h"
      15             : #include "cpl_string.h"
      16             : #include "gdal_priv.h"
      17             : #include "test_data.h"
      18             : 
      19             : #include "gtest_include.h"
      20             : 
      21             : namespace
      22             : {
      23             : 
      24             : // ---------------------------------------------------------------------------
      25             : 
      26             : class MyRasterBand : public GDALRasterBand
      27             : {
      28             :     int bBusy;
      29             : 
      30             :   public:
      31           1 :     MyRasterBand()
      32           1 :     {
      33           1 :         nBlockXSize = 1;
      34           1 :         nBlockYSize = 1;
      35           1 :         bBusy = FALSE;
      36           1 :     }
      37             : 
      38           0 :     CPLErr IReadBlock(int, int, void *) CPL_OVERRIDE
      39             :     {
      40           0 :         CPLAssert(FALSE);
      41             :         return CE_Failure;
      42             :     }
      43             : 
      44           2 :     CPLErr IWriteBlock(int nXBlock, int nYBlock, void *) CPL_OVERRIDE
      45             :     {
      46           2 :         printf("Entering IWriteBlock(%d, %d)\n", nXBlock, nYBlock);
      47           2 :         EXPECT_TRUE(!bBusy);
      48           2 :         bBusy = TRUE;
      49           2 :         CPLSleep(0.5);
      50           2 :         bBusy = FALSE;
      51           2 :         printf("Leaving IWriteBlock(%d, %d)\n", nXBlock, nYBlock);
      52           2 :         return CE_None;
      53             :     }
      54             : };
      55             : 
      56             : class MyDataset : public GDALDataset
      57             : {
      58             :   public:
      59           1 :     MyDataset()
      60           1 :     {
      61           1 :         eAccess = GA_Update;
      62           1 :         nRasterXSize = 2;
      63           1 :         nRasterYSize = 1;
      64           1 :         SetBand(1, new MyRasterBand());
      65           1 :     }
      66             : 
      67           2 :     ~MyDataset()
      68           1 :     {
      69           1 :         FlushCache(true);
      70           2 :     }
      71             : };
      72             : 
      73           1 : static void thread_func1(void * /* unused */)
      74             : {
      75           1 :     printf("begin thread\n");
      76           1 :     GDALFlushCacheBlock();
      77           1 :     printf("end of thread\n\n");
      78           1 : }
      79             : 
      80           1 : static void test1()
      81             : {
      82             :     CPLJoinableThread *hThread;
      83             : 
      84           1 :     printf("Start test1\n");
      85           1 :     printf("main thread %p\n", (void *)CPLGetPID());
      86             : 
      87           1 :     GDALSetCacheMax(0);
      88             : 
      89           1 :     MyDataset *poDS = new MyDataset();
      90             : 
      91           1 :     char buf1[] = {1};
      92           1 :     CPL_IGNORE_RET_VAL(GDALRasterIO(GDALGetRasterBand(poDS, 1), GF_Write, 0, 0,
      93             :                                     1, 1, buf1, 1, 1, GDT_Byte, 0, 0));
      94             : 
      95           1 :     hThread = CPLCreateJoinableThread(thread_func1, nullptr);
      96           1 :     CPLSleep(0.3);
      97           1 :     CPL_IGNORE_RET_VAL(GDALRasterIO(GDALGetRasterBand(poDS, 1), GF_Write, 1, 0,
      98             :                                     1, 1, buf1, 1, 1, GDT_Byte, 0, 0));
      99           1 :     GDALFlushCacheBlock();
     100             : 
     101           1 :     CPLJoinThread(hThread);
     102             : 
     103           1 :     delete poDS;
     104           1 :     printf("End test1\n");
     105           1 : }
     106             : 
     107           1 : static void thread_func2(void * /* unused */)
     108             : {
     109           1 :     printf("begin thread %p\n", (void *)CPLGetPID());
     110           1 :     GDALDatasetH hDS = GDALOpen(TUT_ROOT_DATA_DIR "/byte.tif", GA_ReadOnly);
     111           1 :     GByte c = 0;
     112           1 :     CPL_IGNORE_RET_VAL(GDALDataset::FromHandle(hDS)->GetRasterBand(1)->RasterIO(
     113             :         GF_Read, 0, 0, 1, 1, &c, 1, 1, GDT_Byte, 0, 0, nullptr));
     114           1 :     GDALClose(hDS);
     115           1 :     printf("end of thread\n\n");
     116           1 : }
     117             : 
     118           1 : static void test2()
     119             : {
     120           1 :     printf("Start test2\n");
     121           1 :     printf("main thread %p\n", (void *)CPLGetPID());
     122             : 
     123             :     CPLJoinableThread *hThread;
     124             : 
     125           1 :     CPLSetConfigOption("GDAL_RB_INTERNALIZE_SLEEP_AFTER_DETACH_BEFORE_WRITE",
     126             :                        "0.5");
     127           1 :     GDALSetCacheMax(1000 * 1000);
     128             : 
     129           1 :     auto poDS = GetGDALDriverManager()->GetDriverByName("GTiff")->Create(
     130             :         "/vsimem/foo.tif", 1, 1, 2, GDT_Byte, nullptr);
     131           1 :     poDS->GetRasterBand(1)->Fill(0);
     132           1 :     poDS->GetRasterBand(2)->Fill(0);
     133           1 :     poDS->FlushCache(false);
     134           1 :     GDALSetCacheMax(0);
     135             : 
     136           1 :     poDS->GetRasterBand(1)->Fill(1);
     137           1 :     hThread = CPLCreateJoinableThread(thread_func2, nullptr);
     138           1 :     CPLSleep(0.2);
     139             : 
     140           1 :     GByte c = 0;
     141           1 :     CPL_IGNORE_RET_VAL(poDS->GetRasterBand(1)->RasterIO(
     142             :         GF_Read, 0, 0, 1, 1, &c, 1, 1, GDT_Byte, 0, 0, nullptr));
     143           1 :     printf("%d\n", c);
     144           1 :     ASSERT_EQ(c, 1);
     145           1 :     CPLJoinThread(hThread);
     146             : 
     147           1 :     CPLSetConfigOption("GDAL_RB_INTERNALIZE_SLEEP_AFTER_DETACH_BEFORE_WRITE",
     148             :                        nullptr);
     149           1 :     delete poDS;
     150           1 :     VSIUnlink("/vsimem/foo.tif");
     151           1 :     printf("End test2\n");
     152             : }
     153             : 
     154             : // ---------------------------------------------------------------------------
     155             : 
     156           4 : TEST(testblockcachelimits, test)
     157             : {
     158           1 :     CPLSetConfigOption("GDAL_DEBUG_BLOCK_CACHE", "ON");
     159           1 :     GDALGetCacheMax();
     160             : 
     161           1 :     GDALAllRegister();
     162             : 
     163           1 :     test1();
     164           1 :     test2();
     165             : 
     166           1 :     GDALDestroyDriverManager();
     167           1 : }
     168             : 
     169             : }  // namespace

Generated by: LCOV version 1.14