Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

maporacle - using dynamically-allocated buffers for constructing SQL queries #6282

Merged
merged 7 commits into from
Apr 14, 2021

Conversation

pmauduit
Copy link
Contributor

@pmauduit pmauduit commented Apr 6, 2021

Since the beginning of this driver, we seem to use stack-allocated memory slots to build the SQL queries. One of our customer regularly asks us to build oracle-activated versions of Mapserver, and depending on his usage, asks us to increase the buffers sizes used in the different arrays.

At a given point, e.g. using queries built on top of an SLD parameter, the generated SQL queries were in the need of more and more memory (last one fit in a 294KB text file), so increasing the array size were not an option, and we tried the following work as to rewrite it with dynamically allocated buffers.

I tried to stay close to the Mapserver's code and use functions provided in the msstring.cpp file (msStringConcatenate and so on) ; after some rapid tests against our customer's infrastructure, I haven't detected memleaks at runtime using valgrind, and the current code does not seem to crash.

During the test phase, we also discover 5 allocated pointers which were not freed before returning (see specific commit).

I added a msautotests/msoracle directory but I haven't actually used it. Oracle provides a virtualbox VM with some of these advertised tools, including an Oracle DB with Oracle Spatial, and I was only able to connect onto the oracle spatial installed in the VM - then getting an error "table does not exist", and I haven't been further, as in the meantime I got access to my customer's one.

Note: it was previously written against the 7.6 branch, I cherry-picked the different commits to realign with main, recompile / retest to make sure it was still functionning as expected, but I might have missed something.

this has been revealed using valgrind, before the patch (output
voluntarily truncated):

```
==1959886== 731 bytes in 1 blocks are definitely lost in loss record 193 of 272
==1959886==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==1959886==    by 0x48E155E: msSplitData (maporaclespatial.c:366)
==1959886==    by 0x48ED06B: msOracleSpatialLayerTranslateFilter (maporaclespatial.c:3574)
==1959886==
==1959886== 731 bytes in 1 blocks are definitely lost in loss record 194 of 272
==1959886==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==1959886==    by 0x48E1577: msSplitData (maporaclespatial.c:367)
==1959886==    by 0x48ED06B: msOracleSpatialLayerTranslateFilter (maporaclespatial.c:3574)
==1959886==
==1959886== 731 bytes in 1 blocks are definitely lost in loss record 195 of 272
==1959886==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==1959886==    by 0x48E1590: msSplitData (maporaclespatial.c:368)
==1959886==    by 0x48ED06B: msOracleSpatialLayerTranslateFilter (maporaclespatial.c:3574)
==1959886==
==1959886== 731 bytes in 1 blocks are definitely lost in loss record 196 of 272
==1959886==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==1959886==    by 0x48E15A9: msSplitData (maporaclespatial.c:369)
==1959886==    by 0x48ED06B: msOracleSpatialLayerTranslateFilter (maporaclespatial.c:3574)
==1959886==
==1959886== 2,000 bytes in 1 blocks are definitely lost in loss record 224 of 272
==1959886==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==1959886==    by 0x48ED030: msOracleSpatialLayerTranslateFilter (maporaclespatial.c:3573)
==1959886==    by 0x49896C7: msLayerTranslateFilter (maplayer.c:277)
==1959886==    by 0x498970D: msLayerWhichShapes (maplayer.c:293)
==1959886==    by 0x49BDA0E: msDrawVectorLayer (mapdraw.c:993)
==1959886==    by 0x49BD069: msDrawLayer (mapdraw.c:820)
==1959886==    by 0x49BBBA5: msDrawMap (mapdraw.c:397)
==1959886==    by 0x48FE8F4: msWMSGetMap (mapwms.c:3977)
==1959886==    by 0x4903BC6: msWMSDispatch (mapwms.c:5350)
==1959886==    by 0x4917DC8: msOWSDispatch (mapows.c:289)
==1959886==    by 0x4925ADD: msCGIDispatchRequest (mapservutil.c:1709)
==1959886==    by 0x10979C: main (mapserv.c:283)

```

After:

```
[...]
==1961590== 139,264 bytes in 1 blocks are possibly lost in loss record 266 of 267
==1961590==    at 0x483AB65: calloc (vg_replace_malloc.c:760)
==1961590==    by 0x5D5A380: slwmmgetmem (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x5D5A118: lmmstvrt (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x5D58AB1: lmmstchnk (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x5D59F9D: lmmstsml (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x761F5C9: lmmstmalloc (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x761EBF5: lmmmalloc (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x5D56A54: lmmcis (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x5D5B9E0: lpmpali (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x5D5AC8C: lpminitm (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x5D5AA73: lpminit (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==    by 0x5D3F34F: lfvLoadPkg (in /usr/lib/oracle/11.2/client64/lib/libclntsh.so.11.1)
==1961590==
==1961590== LEAK SUMMARY:
==1961590==    definitely lost: 46 bytes in 1 blocks
==1961590==    indirectly lost: 0 bytes in 0 blocks
==1961590==      possibly lost: 139,648 bytes in 3 blocks
==1961590==    still reachable: 832,783 bytes in 275 blocks
==1961590==         suppressed: 0 bytes in 0 blocks
==1961590== Reachable blocks (those to which a pointer was found) are not shown.
==1961590== To see them, rerun with: --leak-check=full --show-leak-kinds=all
```

The remaining leaks are as above due to the oracle client library.
@jmckenna jmckenna added this to the 8.0 Release milestone Apr 6, 2021
@jmckenna
Copy link
Member

jmckenna commented Apr 6, 2021

Thanks @pmauduit these look like great updates for the Oracle driver. And thanks for including an Oracle test in msautotest, let's see how it runs here....

@pmauduit
Copy link
Contributor Author

pmauduit commented Apr 6, 2021

Thanks @pmauduit these look like great updates for the Oracle driver. And thanks for including an Oracle test in msautotest, let's see how it runs here....

That is the complicated thing here: having an Oracle DB with Oracle Spatial is not an easy task ; I tried using the following VM:
https://www.oracle.com/database/technologies/bigdatalite-v411.html

but it's pretty huge to download, and I was not able to load geographical datas into it, before having access to my customer's one, so I left it in this current state. I kept it only for documentation purposes (we need this TNS_ADMIN env variable pointing to a directory containing this tnsnames.ora file to be able to connect onto an Oracle db).

@rouault
Copy link
Contributor

rouault commented Apr 6, 2021

QGIS has some CI testing for Oracle ( https://github.com/qgis/QGIS/blob/master/.docker/docker-compose-testing-oracle.yml ) . I guess part of it could be reused. A first step would be to have a CI build against the OCI library, which we don't have currently, before performing the tests themselves. Not making that a requirement for this PR though.

@pmauduit
Copy link
Contributor Author

pmauduit commented Apr 7, 2021

QGIS has some CI testing for Oracle ( https://github.com/qgis/QGIS/blob/master/.docker/docker-compose-testing-oracle.yml ) . I guess part of it could be reused.

I had a look, the docker image is quite huge (3.5GB) but still far less than the VM I mentioned previously. I am also a bit concerned about the licensing issues, but might it be fair use ? And if Qgis is already making use of it, maybe it is also ok to reuse it here as well.

@rouault
Copy link
Contributor

rouault commented Apr 13, 2021

Could you address the following compiler warnings ?

/home/even/mapserver/mapserver/maporaclespatial.c: In function ‘osGeodeticData’:
/home/even/mapserver/mapserver/maporaclespatial.c:720:48: warning: unused parameter ‘version’ [-Wunused-parameter]
  720 | static char * osGeodeticData(int function, int version, char *query_str, char *geom_column_name, char *index_column_name, char *srid, rectObj rect)
      |                                            ~~~~^~~~~~~
/home/even/mapserver/mapserver/maporaclespatial.c:720:129: warning: unused parameter ‘srid’ [-Wunused-parameter]
  720 | static char * osGeodeticData(int function, int version, char *query_str, char *geom_column_name, char *index_column_name, char *srid, rectObj rect)
      |                                                                                                                           ~~~~~~^~~~
/home/even/mapserver/mapserver/maporaclespatial.c:720:143: warning: unused parameter ‘rect’ [-Wunused-parameter]
  720 | static char * osGeodeticData(int function, int version, char *query_str, char *geom_column_name, char *index_column_name, char *srid, rectObj rect)
      |                                                                                                                                       ~~~~~~~~^~~~
/home/even/mapserver/mapserver/maporaclespatial.c: In function ‘osNoGeodeticData’:
/home/even/mapserver/mapserver/maporaclespatial.c:777:131: warning: unused parameter ‘srid’ [-Wunused-parameter]
  777 | static char * osNoGeodeticData(int function, int version, char *query_str, char *geom_column_name, char *index_column_name, char *srid, rectObj rect)
      |                                                                                                                             ~~~~~~^~~~
/home/even/mapserver/mapserver/maporaclespatial.c:777:145: warning: unused parameter ‘rect’ [-Wunused-parameter]
  777 | static char * osNoGeodeticData(int function, int version, char *query_str, char *geom_column_name, char *index_column_name, char *srid, rectObj rect)
      |                                                                                                                                         ~~~~~~~~^~~~
/home/even/mapserver/mapserver/maporaclespatial.c: In function ‘osFilteritem’:
/home/even/mapserver/mapserver/maporaclespatial.c:1049:29: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
 1049 |      char * native_filter = msLayerGetProcessingKey(layer, "NATIVE_FILTER");
      |                             ^~~~~~~~~~~~~~~~~~~~~~~

Note: the unused parameters have already been removed in main, this was
a mistake when I rebased my working branch onto main.
@pmauduit
Copy link
Contributor Author

pmauduit commented Apr 14, 2021

Ok done ; for the unused parameters, it was already been done in the main branch, but I reintroduced them when targeting main for this PR.

@rouault rouault merged commit ba2211f into MapServer:main Apr 14, 2021
@jmckenna
Copy link
Member

@pmauduit to confirm, you solved the Oracle msautotest issue, correct?

@pmauduit
Copy link
Contributor Author

@pmauduit to confirm, you solved the Oracle msautotest issue, correct?

It depends of what you mean with the msautotest issues: I reused the docker image from Oslandia, and I was able to load some sample datas taking inspiration of what they did on QGis. I documented the process here:
https://github.com/MapServer/MapServer/blob/main/msautotest/msoracle/README.md

This allows to have an Oracle Spatial where I can launch the added msautotest against. The expected/oracle.png is compliant with the mapfile oracle.map provided.

But if you have a CI in mind, there is still some work to be done, basically:

  1. compile Mapserver against the oracle client libraries (libOCI), which are not easily obtainable (need an Oracle account)
  2. launch the docker-composition in the msoracle sub-directory: https://github.com/MapServer/MapServer/blob/main/msautotest/msoracle/docker-compose.yaml
  3. python run_tests.py

@pmauduit pmauduit deleted the dynamic-buffer-oracle-spatial-main branch April 14, 2021 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants