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: 2024-11-21 22:18:42 Functions: 13 14 92.9 %

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

Generated by: LCOV version 1.14