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
|