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 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_multiproc.h"
31 : #include "cpl_string.h"
32 : #include "cpl_virtualmem.h"
33 : #include "gdal_alg.h"
34 : #include "gdal.h"
35 :
36 : #include "gtest_include.h"
37 :
38 : #include "test_data.h"
39 :
40 : namespace
41 : {
42 :
43 : // ---------------------------------------------------------------------------
44 :
45 : #ifdef notdef
46 : static void test_huge_mapping_cbk(CPLVirtualMem *ctxt, size_t nOffset,
47 : void *pPageToFill, size_t nPageSize,
48 : void *pUserData)
49 : {
50 : /*fprintfstderr("requesting page %lu (nPageSize=%d), nLRUSize=%d\n",
51 : (unsigned long)(nOffset / nPageSize),
52 : (int)nPageSize,
53 : ctxt->nLRUSize);*/
54 : memset(pPageToFill, 0x7F, nPageSize);
55 : }
56 :
57 : static void test_huge_mapping()
58 : {
59 : CPLVirtualMem *ctxt;
60 : char *addr;
61 : int i;
62 :
63 : ctxt = CPLVirtualMemNew(
64 : (size_t)10000 * 1024 * 1024, (size_t)2000 * 1024 * 1024, 0, TRUE,
65 : VIRTUALMEM_READONLY, test_huge_mapping_cbk, NULL, NULL, NULL);
66 : ASSERT_TRUE(ctxt != nullptr);
67 : addr = (char *)CPLVirtualMemGetAddr(ctxt);
68 : for (i = 0; i < 50 * 1000; i++)
69 : {
70 : unsigned int seedp;
71 : size_t idx = (size_t)rand_r(&seedp) * 3000 * 1024 / RAND_MAX * 1024;
72 : char val = addr[idx];
73 : /*printf("i=%d, val[%ld] = %d\n", i, (long int)idx, val);*/
74 : ASSERT_EQ(val, 0x7F);
75 : }
76 : CPLVirtualMemFree(ctxt);
77 : }
78 : #endif
79 :
80 50501 : static void test_two_pages_cbk(CPLVirtualMem * /* ctxt */, size_t nOffset,
81 : void *pPageToFill, size_t nPageSize,
82 : void * /* pUserData */)
83 : {
84 : /*fprintfstderr("requesting page %lu (nPageSize=%d), nLRUSize=%d\n",
85 : (unsigned long)(nOffset / nPageSize),
86 : (int)nPageSize,
87 : ctxt->nLRUSize);*/
88 84168 : memset(pPageToFill,
89 : (nOffset == 0) ? 0x3F
90 33667 : : (nOffset == 4096) ? 0x5F
91 : : 0x7F,
92 : nPageSize);
93 50501 : }
94 :
95 : #define MINIMUM_PAGE_SIZE 4096
96 :
97 1 : static void test_two_pages_thread(void *p)
98 : {
99 1 : CPLVirtualMem *ctxt = (CPLVirtualMem *)p;
100 1 : char *addr = (char *)CPLVirtualMemGetAddr(ctxt);
101 : int i;
102 1 : CPLVirtualMemDeclareThread(ctxt);
103 : /*fprintfstderr("aux thread is %X\n", pthread_self());*/
104 :
105 50001 : for (i = 0; i < 50 * 1000; i++)
106 : {
107 50000 : char val =
108 50000 : addr[MINIMUM_PAGE_SIZE * (i % 3) + MINIMUM_PAGE_SIZE / 2 - 1];
109 : /*fprintfstderr("T2: val[%d] = %d\n", MINIMUM_PAGE_SIZE * (i % 2) +
110 : * MINIMUM_PAGE_SIZE/2 - 1, val);*/
111 50000 : ASSERT_EQ(val, (((i % 3) == 0) ? 0x3F : ((i % 3) == 1) ? 0x5F : 0x7F));
112 : }
113 1 : CPLVirtualMemUnDeclareThread(ctxt);
114 : }
115 :
116 1 : static void test_two_pages(CPLVirtualMem *ctxt)
117 : {
118 : volatile char *addr;
119 : CPLJoinableThread *hThread;
120 :
121 1 : printf("test_two_pages()\n");
122 :
123 1 : addr = (char *)CPLVirtualMemGetAddr(ctxt);
124 1 : ASSERT_EQ(CPLVirtualMemGetPageSize(ctxt), MINIMUM_PAGE_SIZE);
125 1 : ASSERT_TRUE(CPLVirtualMemIsAccessThreadSafe(ctxt));
126 : /*fprintfstderr("main thread is %X, addr=%p\n", pthread_self(), addr);*/
127 1 : hThread = CPLCreateJoinableThread(test_two_pages_thread, ctxt);
128 1 : CPLVirtualMemDeclareThread(ctxt);
129 : {
130 1 : int i = 0;
131 50001 : for (i = 0; i < 50 * 1000; i++)
132 : {
133 50000 : char val = addr[MINIMUM_PAGE_SIZE * (i % 3)];
134 : /*fprintfstderr("T1: val[%d] = %d\n", MINIMUM_PAGE_SIZE * (i % 2),
135 : * val);*/
136 50000 : ASSERT_EQ(val, (((i % 3) == 0) ? 0x3F
137 : : ((i % 3) == 1) ? 0x5F
138 : : 0x7F));
139 : }
140 : }
141 1 : CPLVirtualMemUnDeclareThread(ctxt);
142 1 : CPLJoinThread(hThread);
143 1 : CPLVirtualMemFree(ctxt);
144 : }
145 :
146 4 : static void test_raw_auto(const char *pszFormat, int bFileMapping)
147 : {
148 4 : GDALAllRegister();
149 :
150 4 : printf("test_raw_auto(format=%s, bFileMapping=%d)\n", pszFormat,
151 : bFileMapping);
152 4 : if (GDALGetDriverByName(pszFormat) == nullptr)
153 : {
154 0 : GTEST_SKIP() << pszFormat << " driver missing";
155 : return;
156 : }
157 :
158 4 : CPLString osTmpFile;
159 :
160 4 : if (bFileMapping)
161 : osTmpFile =
162 2 : CPLResetExtension(CPLGenerateTempFilename(pszFormat), "img");
163 : else
164 2 : osTmpFile = "/vsimem/tmp.img";
165 : GDALDatasetH hDS =
166 4 : GDALCreate(GDALGetDriverByName(pszFormat), osTmpFile.c_str(), 400, 300,
167 : 2, GDT_Byte, nullptr);
168 4 : ASSERT_TRUE(hDS != nullptr);
169 :
170 : int nPixelSpace1;
171 : GIntBig nLineSpace1;
172 : int nPixelSpace2;
173 : GIntBig nLineSpace2;
174 4 : if (!bFileMapping)
175 : {
176 : char **papszOptions =
177 2 : CSLSetNameValue(nullptr, "USE_DEFAULT_IMPLEMENTATION", "NO");
178 2 : ASSERT_EQ(GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 1), GF_Write,
179 : &nPixelSpace1, &nLineSpace1,
180 : papszOptions),
181 : nullptr);
182 2 : CSLDestroy(papszOptions);
183 : }
184 : CPLVirtualMem *pVMem1 =
185 4 : GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 1), GF_Write,
186 : &nPixelSpace1, &nLineSpace1, nullptr);
187 4 : char **papszOptions = CSLSetNameValue(nullptr, "USE_DEFAULT_IMPLEMENTATION",
188 4 : (bFileMapping) ? "NO" : "YES");
189 : CPLVirtualMem *pVMem2 =
190 4 : GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 2), GF_Write,
191 : &nPixelSpace2, &nLineSpace2, papszOptions);
192 4 : CSLDestroy(papszOptions);
193 4 : ASSERT_TRUE(pVMem1 != nullptr);
194 4 : ASSERT_TRUE(pVMem2 != nullptr);
195 4 : ASSERT_EQ(CPLVirtualMemIsFileMapping(pVMem1), bFileMapping);
196 4 : ASSERT_EQ(nPixelSpace1,
197 : ((EQUAL(pszFormat, "GTIFF") && bFileMapping) ? 2 : 1));
198 4 : if (bFileMapping)
199 2 : ASSERT_EQ(nLineSpace1, 400 * 2);
200 : else
201 2 : ASSERT_EQ(nLineSpace1, 400 * nPixelSpace1);
202 :
203 4 : GByte *pBase1 = (GByte *)CPLVirtualMemGetAddr(pVMem1);
204 4 : GByte *pBase2 = (GByte *)CPLVirtualMemGetAddr(pVMem2);
205 1204 : for (int j = 0; j < 300; j++)
206 : {
207 481200 : for (int i = 0; i < 400; i++)
208 : {
209 480000 : pBase1[j * static_cast<int>(nLineSpace1) + i * nPixelSpace1] = 127;
210 480000 : pBase2[j * static_cast<int>(nLineSpace2) + i * nPixelSpace2] = 255;
211 : }
212 : }
213 :
214 4 : CPLVirtualMemFree(pVMem1);
215 4 : CPLVirtualMemFree(pVMem2);
216 4 : GDALClose(hDS);
217 :
218 4 : hDS = GDALOpen(osTmpFile.c_str(), GA_ReadOnly);
219 4 : ASSERT_EQ(GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, 400, 300),
220 : 52906);
221 4 : ASSERT_EQ(GDALChecksumImage(GDALGetRasterBand(hDS, 2), 0, 0, 400, 300),
222 : 30926);
223 4 : GDALClose(hDS);
224 :
225 4 : GDALDeleteDataset(nullptr, osTmpFile.c_str());
226 : }
227 :
228 4 : TEST(testvitualmem, test)
229 : {
230 1 : if (getenv("SKIP_TESTVIRTUALMEM") != nullptr)
231 : {
232 0 : fprintf(stderr, "Skipping testvitualmem\n"); // ok
233 0 : return;
234 : }
235 :
236 : /*printf("test_huge_mapping\n");
237 : test_huge_mapping();*/
238 :
239 1 : printf("Physical memory : " CPL_FRMT_GIB " bytes\n", CPLGetPhysicalRAM());
240 :
241 1 : if (CPLIsVirtualMemFileMapAvailable())
242 : {
243 1 : printf("Testing CPLVirtualMemFileMapNew()\n");
244 1 : VSILFILE *fp = VSIFOpenL(GCORE_DATA_DIR "byte.tif", "rb");
245 1 : ASSERT_TRUE(fp != nullptr);
246 1 : VSIFSeekL(fp, 0, SEEK_END);
247 1 : size_t nSize = (size_t)VSIFTellL(fp);
248 1 : VSIFSeekL(fp, 0, SEEK_SET);
249 1 : void *pRefBuf = CPLMalloc(nSize);
250 1 : VSIFReadL(pRefBuf, 1, nSize, fp);
251 1 : CPLVirtualMem *psMem = CPLVirtualMemFileMapNew(
252 : fp, 0, nSize, VIRTUALMEM_READONLY, nullptr, nullptr);
253 1 : ASSERT_TRUE(psMem != nullptr);
254 1 : void *pMemBuf = CPLVirtualMemGetAddr(psMem);
255 1 : ASSERT_TRUE(memcmp(pRefBuf, pMemBuf, nSize) == 0);
256 1 : CPLFree(pRefBuf);
257 1 : CPLVirtualMemFree(psMem);
258 1 : VSIFCloseL(fp);
259 : }
260 :
261 1 : auto ctxt = CPLVirtualMemNew(3 * MINIMUM_PAGE_SIZE, MINIMUM_PAGE_SIZE,
262 : MINIMUM_PAGE_SIZE, FALSE, VIRTUALMEM_READONLY,
263 : test_two_pages_cbk, nullptr, nullptr, nullptr);
264 1 : if (ctxt)
265 : {
266 1 : test_two_pages(ctxt);
267 1 : test_raw_auto("EHDR", TRUE);
268 1 : test_raw_auto("EHDR", FALSE);
269 1 : test_raw_auto("GTIFF", TRUE);
270 1 : test_raw_auto("GTIFF", FALSE);
271 : }
272 :
273 1 : CPLVirtualMemManagerTerminate();
274 1 : GDALDestroyDriverManager();
275 : }
276 :
277 : } // namespace
|