Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL algorithms
4 : * Purpose: Test Delaunay triangulation
5 : * Author: Even Rouault, even.rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2014, Even Rouault <even.rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "cpl_multiproc.h"
14 : #include "cpl_string.h"
15 : #include "cpl_virtualmem.h"
16 : #include "gdal_alg.h"
17 : #include "gdal.h"
18 :
19 : #include "gtest_include.h"
20 :
21 : #include "test_data.h"
22 :
23 : namespace
24 : {
25 :
26 : // ---------------------------------------------------------------------------
27 :
28 : #ifdef notdef
29 : static void test_huge_mapping_cbk(CPLVirtualMem *ctxt, size_t nOffset,
30 : void *pPageToFill, size_t nPageSize,
31 : void *pUserData)
32 : {
33 : /*fprintfstderr("requesting page %lu (nPageSize=%d), nLRUSize=%d\n",
34 : (unsigned long)(nOffset / nPageSize),
35 : (int)nPageSize,
36 : ctxt->nLRUSize);*/
37 : memset(pPageToFill, 0x7F, nPageSize);
38 : }
39 :
40 : static void test_huge_mapping()
41 : {
42 : CPLVirtualMem *ctxt;
43 : char *addr;
44 : int i;
45 :
46 : ctxt = CPLVirtualMemNew(
47 : (size_t)10000 * 1024 * 1024, (size_t)2000 * 1024 * 1024, 0, TRUE,
48 : VIRTUALMEM_READONLY, test_huge_mapping_cbk, NULL, NULL, NULL);
49 : ASSERT_TRUE(ctxt != nullptr);
50 : addr = (char *)CPLVirtualMemGetAddr(ctxt);
51 : for (i = 0; i < 50 * 1000; i++)
52 : {
53 : unsigned int seedp;
54 : size_t idx = (size_t)rand_r(&seedp) * 3000 * 1024 / RAND_MAX * 1024;
55 : char val = addr[idx];
56 : /*printf("i=%d, val[%ld] = %d\n", i, (long int)idx, val);*/
57 : ASSERT_EQ(val, 0x7F);
58 : }
59 : CPLVirtualMemFree(ctxt);
60 : }
61 : #endif
62 :
63 68558 : static void test_two_pages_cbk(CPLVirtualMem * /* ctxt */, size_t nOffset,
64 : void *pPageToFill, size_t nPageSize,
65 : void * /* pUserData */)
66 : {
67 : /*fprintfstderr("requesting page %lu (nPageSize=%d), nLRUSize=%d\n",
68 : (unsigned long)(nOffset / nPageSize),
69 : (int)nPageSize,
70 : ctxt->nLRUSize);*/
71 114263 : memset(pPageToFill,
72 : (nOffset == 0) ? 0x3F
73 45705 : : (nOffset == 4096) ? 0x5F
74 : : 0x7F,
75 : nPageSize);
76 68558 : }
77 :
78 : #define MINIMUM_PAGE_SIZE 4096
79 :
80 1 : static void test_two_pages_thread(void *p)
81 : {
82 1 : CPLVirtualMem *ctxt = (CPLVirtualMem *)p;
83 1 : char *addr = (char *)CPLVirtualMemGetAddr(ctxt);
84 : int i;
85 1 : CPLVirtualMemDeclareThread(ctxt);
86 : /*fprintfstderr("aux thread is %X\n", pthread_self());*/
87 :
88 50001 : for (i = 0; i < 50 * 1000; i++)
89 : {
90 50000 : char val =
91 50000 : addr[MINIMUM_PAGE_SIZE * (i % 3) + MINIMUM_PAGE_SIZE / 2 - 1];
92 : /*fprintfstderr("T2: val[%d] = %d\n", MINIMUM_PAGE_SIZE * (i % 2) +
93 : * MINIMUM_PAGE_SIZE/2 - 1, val);*/
94 50000 : ASSERT_EQ(val, (((i % 3) == 0) ? 0x3F : ((i % 3) == 1) ? 0x5F : 0x7F));
95 : }
96 1 : CPLVirtualMemUnDeclareThread(ctxt);
97 : }
98 :
99 1 : static void test_two_pages(CPLVirtualMem *ctxt)
100 : {
101 : volatile char *addr;
102 : CPLJoinableThread *hThread;
103 :
104 1 : printf("test_two_pages()\n");
105 :
106 1 : addr = (char *)CPLVirtualMemGetAddr(ctxt);
107 1 : ASSERT_EQ(CPLVirtualMemGetPageSize(ctxt), MINIMUM_PAGE_SIZE);
108 1 : ASSERT_TRUE(CPLVirtualMemIsAccessThreadSafe(ctxt));
109 : /*fprintfstderr("main thread is %X, addr=%p\n", pthread_self(), addr);*/
110 1 : hThread = CPLCreateJoinableThread(test_two_pages_thread, ctxt);
111 1 : CPLVirtualMemDeclareThread(ctxt);
112 : {
113 1 : int i = 0;
114 50001 : for (i = 0; i < 50 * 1000; i++)
115 : {
116 50000 : char val = addr[MINIMUM_PAGE_SIZE * (i % 3)];
117 : /*fprintfstderr("T1: val[%d] = %d\n", MINIMUM_PAGE_SIZE * (i % 2),
118 : * val);*/
119 50000 : ASSERT_EQ(val, (((i % 3) == 0) ? 0x3F
120 : : ((i % 3) == 1) ? 0x5F
121 : : 0x7F));
122 : }
123 : }
124 1 : CPLVirtualMemUnDeclareThread(ctxt);
125 1 : CPLJoinThread(hThread);
126 1 : CPLVirtualMemFree(ctxt);
127 : }
128 :
129 4 : static void test_raw_auto(const char *pszFormat, int bFileMapping)
130 : {
131 4 : GDALAllRegister();
132 :
133 4 : printf("test_raw_auto(format=%s, bFileMapping=%d)\n", pszFormat,
134 : bFileMapping);
135 4 : if (GDALGetDriverByName(pszFormat) == nullptr)
136 : {
137 0 : GTEST_SKIP() << pszFormat << " driver missing";
138 : return;
139 : }
140 :
141 4 : CPLString osTmpFile;
142 :
143 4 : if (bFileMapping)
144 2 : osTmpFile = CPLResetExtensionSafe(
145 4 : CPLGenerateTempFilenameSafe(pszFormat).c_str(), "img");
146 : else
147 2 : osTmpFile = "/vsimem/tmp.img";
148 : GDALDatasetH hDS =
149 4 : GDALCreate(GDALGetDriverByName(pszFormat), osTmpFile.c_str(), 400, 300,
150 : 2, GDT_Byte, nullptr);
151 4 : ASSERT_TRUE(hDS != nullptr);
152 :
153 : int nPixelSpace1;
154 : GIntBig nLineSpace1;
155 : int nPixelSpace2;
156 : GIntBig nLineSpace2;
157 4 : if (!bFileMapping)
158 : {
159 : char **papszOptions =
160 2 : CSLSetNameValue(nullptr, "USE_DEFAULT_IMPLEMENTATION", "NO");
161 2 : ASSERT_EQ(GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 1), GF_Write,
162 : &nPixelSpace1, &nLineSpace1,
163 : papszOptions),
164 : nullptr);
165 2 : CSLDestroy(papszOptions);
166 : }
167 : CPLVirtualMem *pVMem1 =
168 4 : GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 1), GF_Write,
169 : &nPixelSpace1, &nLineSpace1, nullptr);
170 4 : char **papszOptions = CSLSetNameValue(nullptr, "USE_DEFAULT_IMPLEMENTATION",
171 4 : (bFileMapping) ? "NO" : "YES");
172 : CPLVirtualMem *pVMem2 =
173 4 : GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 2), GF_Write,
174 : &nPixelSpace2, &nLineSpace2, papszOptions);
175 4 : CSLDestroy(papszOptions);
176 4 : ASSERT_TRUE(pVMem1 != nullptr);
177 4 : ASSERT_TRUE(pVMem2 != nullptr);
178 4 : ASSERT_EQ(CPLVirtualMemIsFileMapping(pVMem1), bFileMapping);
179 4 : ASSERT_EQ(nPixelSpace1,
180 : ((EQUAL(pszFormat, "GTIFF") && bFileMapping) ? 2 : 1));
181 4 : if (bFileMapping)
182 2 : ASSERT_EQ(nLineSpace1, 400 * 2);
183 : else
184 2 : ASSERT_EQ(nLineSpace1, 400 * nPixelSpace1);
185 :
186 4 : GByte *pBase1 = (GByte *)CPLVirtualMemGetAddr(pVMem1);
187 4 : GByte *pBase2 = (GByte *)CPLVirtualMemGetAddr(pVMem2);
188 1204 : for (int j = 0; j < 300; j++)
189 : {
190 481200 : for (int i = 0; i < 400; i++)
191 : {
192 480000 : pBase1[j * static_cast<int>(nLineSpace1) + i * nPixelSpace1] = 127;
193 480000 : pBase2[j * static_cast<int>(nLineSpace2) + i * nPixelSpace2] = 255;
194 : }
195 : }
196 :
197 4 : CPLVirtualMemFree(pVMem1);
198 4 : CPLVirtualMemFree(pVMem2);
199 4 : GDALClose(hDS);
200 :
201 4 : hDS = GDALOpen(osTmpFile.c_str(), GA_ReadOnly);
202 4 : ASSERT_EQ(GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, 400, 300),
203 : 52906);
204 4 : ASSERT_EQ(GDALChecksumImage(GDALGetRasterBand(hDS, 2), 0, 0, 400, 300),
205 : 30926);
206 4 : GDALClose(hDS);
207 :
208 4 : GDALDeleteDataset(nullptr, osTmpFile.c_str());
209 : }
210 :
211 4 : TEST(testvitualmem, test)
212 : {
213 1 : if (getenv("SKIP_TESTVIRTUALMEM") != nullptr)
214 : {
215 0 : fprintf(stderr, "Skipping testvitualmem\n"); // ok
216 0 : return;
217 : }
218 :
219 : /*printf("test_huge_mapping\n");
220 : test_huge_mapping();*/
221 :
222 1 : printf("Physical memory : " CPL_FRMT_GIB " bytes\n", CPLGetPhysicalRAM());
223 :
224 1 : if (CPLIsVirtualMemFileMapAvailable())
225 : {
226 1 : printf("Testing CPLVirtualMemFileMapNew()\n");
227 1 : VSILFILE *fp = VSIFOpenL(GCORE_DATA_DIR "byte.tif", "rb");
228 1 : ASSERT_TRUE(fp != nullptr);
229 1 : VSIFSeekL(fp, 0, SEEK_END);
230 1 : size_t nSize = (size_t)VSIFTellL(fp);
231 1 : VSIFSeekL(fp, 0, SEEK_SET);
232 1 : void *pRefBuf = CPLMalloc(nSize);
233 1 : VSIFReadL(pRefBuf, 1, nSize, fp);
234 1 : CPLVirtualMem *psMem = CPLVirtualMemFileMapNew(
235 : fp, 0, nSize, VIRTUALMEM_READONLY, nullptr, nullptr);
236 1 : ASSERT_TRUE(psMem != nullptr);
237 1 : void *pMemBuf = CPLVirtualMemGetAddr(psMem);
238 1 : ASSERT_TRUE(memcmp(pRefBuf, pMemBuf, nSize) == 0);
239 1 : CPLFree(pRefBuf);
240 1 : CPLVirtualMemFree(psMem);
241 1 : VSIFCloseL(fp);
242 : }
243 :
244 1 : auto ctxt = CPLVirtualMemNew(3 * MINIMUM_PAGE_SIZE, MINIMUM_PAGE_SIZE,
245 : MINIMUM_PAGE_SIZE, FALSE, VIRTUALMEM_READONLY,
246 : test_two_pages_cbk, nullptr, nullptr, nullptr);
247 1 : if (ctxt)
248 : {
249 1 : test_two_pages(ctxt);
250 1 : test_raw_auto("EHDR", TRUE);
251 1 : test_raw_auto("EHDR", FALSE);
252 1 : test_raw_auto("GTIFF", TRUE);
253 1 : test_raw_auto("GTIFF", FALSE);
254 : }
255 :
256 1 : CPLVirtualMemManagerTerminate();
257 1 : GDALDestroyDriverManager();
258 : }
259 :
260 : } // namespace
|