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