[mapserver-commits] r10540 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Wed Sep 29 18:56:11 EDT 2010


Author: warmerdam
Date: 2010-09-29 22:56:11 +0000 (Wed, 29 Sep 2010)
New Revision: 10540

Modified:
   trunk/mapserver/HISTORY.TXT
   trunk/mapserver/mapgdal.c
   trunk/mapserver/maphttp.c
   trunk/mapserver/mapows.h
   trunk/mapserver/mapwmslayer.c
Log:
avoid writing WMS client layer results to disk (#3555)

Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT	2010-09-29 21:40:06 UTC (rev 10539)
+++ trunk/mapserver/HISTORY.TXT	2010-09-29 22:56:11 UTC (rev 10540)
@@ -14,6 +14,8 @@
 Current Version (SVN trunk):
 ----------------------------
 
+- Support holding WMS client requests in RAM instead of writing to disk (#3555)
+
 - RFC-61: Enhance MapServer Feature Style Support (#3544)
 
 - Restrict cascaded WMS requests based on EXTENT (#3543)

Modified: trunk/mapserver/mapgdal.c
===================================================================
--- trunk/mapserver/mapgdal.c	2010-09-29 21:40:06 UTC (rev 10539)
+++ trunk/mapserver/mapgdal.c	2010-09-29 22:56:11 UTC (rev 10540)
@@ -95,7 +95,7 @@
 /*      things are clean before we start, and after we are done.        */
 /************************************************************************/
 
-static void CleanVSIDir( const char *pszDir )
+void CleanVSIDir( const char *pszDir )
 
 {
     char **papszFiles = CPLReadDir( pszDir );

Modified: trunk/mapserver/maphttp.c
===================================================================
--- trunk/mapserver/maphttp.c	2010-09-29 21:40:06 UTC (rev 10539)
+++ trunk/mapserver/maphttp.c	2010-09-29 22:56:11 UTC (rev 10540)
@@ -145,7 +145,9 @@
 
         pasReqInfo[i].curl_handle = NULL;
         pasReqInfo[i].fp = NULL;
-
+        pasReqInfo[i].result_data = NULL;
+        pasReqInfo[i].result_size = 0;
+        pasReqInfo[i].result_buf_size = 0;
     }
 }
 
@@ -192,6 +194,11 @@
         pasReqInfo[i].pszHTTPCookieData = NULL;
 
         pasReqInfo[i].curl_handle = NULL;
+
+        free( pasReqInfo[i].result_data );
+        pasReqInfo[i].result_data = NULL;
+        pasReqInfo[i].result_size = 0;
+        pasReqInfo[i].result_buf_size = 0;
     }
 }
 
@@ -219,7 +226,44 @@
                 psReq->nLayerId, size*nmemb);
     }
 
-    return fwrite(buffer, size, nmemb, psReq->fp);
+    /* Case where we are writing to a disk file. */
+    if( psReq->fp != NULL )
+    {
+        return fwrite(buffer, size, nmemb, psReq->fp);
+    }
+    
+    /* Case where we build up the result in memory */
+    else
+    {
+        if( psReq->result_data == NULL )
+        {
+            psReq->result_buf_size = size*nmemb + 10000;
+            psReq->result_data = (char *) malloc( psReq->result_buf_size );
+        }
+        else if( psReq->result_size + nmemb * size > psReq->result_buf_size )
+        {
+            psReq->result_buf_size = psReq->result_size + nmemb*size + 10000;
+            psReq->result_data = (char *) realloc( psReq->result_data,
+                                                   psReq->result_buf_size );
+        }
+
+        if( psReq->result_data == NULL )
+        {
+            msSetError(MS_HTTPERR, 
+                       "Unable to grow HTTP result buffer to size %d.",
+                       "msHTTPWriteFct()",
+                       psReq->result_buf_size );
+            psReq->result_buf_size = 0;
+            psReq->result_size = 0;
+            return -1;
+        }
+        
+        memcpy( psReq->result_data + psReq->result_size,
+                buffer, size*nmemb );
+        psReq->result_size += size*nmemb;
+
+        return size*nmemb;
+    }
 }
 
 /**********************************************************************
@@ -321,8 +365,7 @@
         CURL *http_handle;
         FILE *fp;
 
-        if (pasReqInfo[i].pszGetUrl == NULL || 
-            pasReqInfo[i].pszOutputFile == NULL)
+        if (pasReqInfo[i].pszGetUrl == NULL )
         {
             msSetError(MS_HTTPERR, "URL or output file parameter missing.", 
                        "msHTTPExecuteRequests()");
@@ -342,7 +385,7 @@
         pasReqInfo[i].pszContentType = NULL;
 
         /* Check local cache if requested */
-        if (bCheckLocalCache)
+        if (bCheckLocalCache && pasReqInfo[i].pszOutputFile != NULL )
         {
             fp = fopen(pasReqInfo[i].pszOutputFile, "r");
             if (fp)
@@ -488,15 +531,19 @@
         curl_easy_setopt(http_handle, CURLOPT_NOSIGNAL, 1 );
 #endif
 
-        /* Open output file and set write handler */
-        if ( (fp = fopen(pasReqInfo[i].pszOutputFile, "wb")) == NULL)
+        /* If we are writing file to disk, open the file now. */
+        if( pasReqInfo[i].pszOutputFile != NULL )
         {
-            msSetError(MS_HTTPERR, "Can't open output file %s.", 
-                       "msHTTPExecuteRequests()", pasReqInfo[i].pszOutputFile);
-            return(MS_FAILURE);
+            if ( (fp = fopen(pasReqInfo[i].pszOutputFile, "wb")) == NULL)
+            {
+                msSetError(MS_HTTPERR, "Can't open output file %s.", 
+                           "msHTTPExecuteRequests()", pasReqInfo[i].pszOutputFile);
+                return(MS_FAILURE);
+            }
+
+            pasReqInfo[i].fp = fp;
         }
 
-        pasReqInfo[i].fp = fp;
         curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, &(pasReqInfo[i]));
         curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, msHTTPWriteFct);
 

Modified: trunk/mapserver/mapows.h
===================================================================
--- trunk/mapserver/mapows.h	2010-09-29 21:40:06 UTC (rev 10539)
+++ trunk/mapserver/mapows.h	2010-09-29 22:56:11 UTC (rev 10540)
@@ -94,6 +94,11 @@
     /* Private members */
     void      * curl_handle;   /* CURLM * handle */
     FILE      * fp;            /* FILE * used during download */
+    
+    char      * result_data;   /* output if pszOutputFile is NULL */
+    int       result_size;
+    int       result_buf_size;
+
 } httpRequestObj;
 
 typedef struct

Modified: trunk/mapserver/mapwmslayer.c
===================================================================
--- trunk/mapserver/mapwmslayer.c	2010-09-29 21:40:06 UTC (rev 10539)
+++ trunk/mapserver/mapwmslayer.c	2010-09-29 22:56:11 UTC (rev 10540)
@@ -39,7 +39,12 @@
 #include <stdio.h>
 #endif
 
+#ifdef USE_GDAL
+#  include "cpl_vsi.h"
+#endif
 
+void CleanVSIDir( const char *pszDir );
+
 /**********************************************************************
  *                          msInitWmsParamsObj()
  *
@@ -934,7 +939,7 @@
     const char *pszTmp;
     rectObj bbox;
     int bbox_width, bbox_height;
-    int nTimeout, bOkToMerge, bForceSeparateRequest;
+    int nTimeout, bOkToMerge, bForceSeparateRequest, bCacheToDisk;
     wmsParamsObj sThisWMSParams;
     
     char    *pszProxyHost=NULL;
@@ -1132,9 +1137,24 @@
             return(MS_FAILURE);  /* An error should already have been produced */
         }
     }
-    
 
 /* ------------------------------------------------------------------
+ * Check if we want to use in memory images instead of writing to disk.
+ * ------------------------------------------------------------------ */
+    if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), 
+                                      "MO", "cache_to_disk")) != NULL)
+    {
+        if( strcasecmp(pszTmp,"true") == 0
+            || strcasecmp(pszTmp,"on") == 0
+            || strcasecmp(pszTmp,"yes") == 0 )
+            bCacheToDisk = MS_TRUE;
+        else
+            bCacheToDisk = atoi(pszTmp);
+    }
+    else
+        bCacheToDisk = MS_FALSE;
+
+/* ------------------------------------------------------------------
  * Check if layer can be merged with previous WMS layer requests
  * Metadata wms_force_separate_request can be set to 1 to prevent this
  * this layer from being combined with any other layer.
@@ -1300,9 +1320,11 @@
         }
         pasReqInfo[(*numRequests)].pszHTTPCookieData = pszHTTPCookieData;
         pszHTTPCookieData = NULL;
-        pasReqInfo[(*numRequests)].pszOutputFile =msTmpFile(map->mappath,
-                                                            map->web.imagepath,
-                                                            "img.tmp");
+        if( bCacheToDisk )
+            pasReqInfo[(*numRequests)].pszOutputFile =
+                msTmpFile(map->mappath, map->web.imagepath, "img.tmp");
+        else
+            pasReqInfo[(*numRequests)].pszOutputFile = NULL;
         pasReqInfo[(*numRequests)].nStatus = 0;
         pasReqInfo[(*numRequests)].nTimeout = nTimeout;
         pasReqInfo[(*numRequests)].bbox   = bbox;
@@ -1371,6 +1393,7 @@
     int currenttype;
     int currentconnectiontype;
     int numclasses;
+    char *mem_filename = NULL;
 
 /* ------------------------------------------------------------------
  * Find the request info for this layer in the array, based on nLayerId
@@ -1455,7 +1478,22 @@
 
         return MS_SUCCESS;
     }
+
+/* ------------------------------------------------------------------
+ * If the output was written to a memory buffer, then we will need
+ * to attach a "VSI" name to this buffer.
+ * ------------------------------------------------------------------ */
+    if( pasReqInfo[iReq].pszOutputFile == NULL )
+    {
+        CleanVSIDir( "/vsimem/msout" );
+        mem_filename = msTmpFile( NULL, "/vsimem/msout/", "img.tmp" );
         
+        VSIFCloseL( 
+            VSIFileFromMemBuffer( mem_filename, 
+                                  (GByte*) pasReqInfo[iReq].result_data,
+                                  (vsi_l_offset) pasReqInfo[iReq].result_size,
+                                  FALSE ) );
+    }
 
 /* ------------------------------------------------------------------
  * Prepare layer for drawing, reprojecting the image received from the
@@ -1481,7 +1519,10 @@
       lp->numclasses = 0;
 
     if (lp->data) free(lp->data);
-    lp->data =  strdup(pasReqInfo[iReq].pszOutputFile);
+    if( mem_filename != NULL )
+        lp->data = mem_filename;
+    else
+        lp->data =  strdup(pasReqInfo[iReq].pszOutputFile);
 
     /* #3138 If PROCESSING "RESAMPLE=..." is set we cannot use the simple case */
     if (!msProjectionsDiffer(&(map->projection), &(lp->projection)) && 
@@ -1507,7 +1548,7 @@
         wldfile = msBuildPath(szPath, lp->map->mappath, lp->data);
         if (wldfile)    
             strcpy(wldfile+strlen(wldfile)-3, "wld");
-        if (wldfile && (fp = fopen(wldfile, "wt")) != NULL)
+        if (wldfile && (fp = VSIFOpenL(wldfile, "wt")) != NULL)
         {
             double dfCellSizeX = MS_CELLSIZE(pasReqInfo[iReq].bbox.minx,
                                              pasReqInfo[iReq].bbox.maxx, 
@@ -1515,23 +1556,23 @@
             double dfCellSizeY = MS_CELLSIZE(pasReqInfo[iReq].bbox.maxy,
                                              pasReqInfo[iReq].bbox.miny, 
                                              pasReqInfo[iReq].height);
-                
-            fprintf(fp, "%.12f\n", dfCellSizeX );
-            fprintf(fp, "0\n");
-            fprintf(fp, "0\n");
-            fprintf(fp, "%.12f\n", dfCellSizeY );
-            fprintf(fp, "%.12f\n", 
-                    pasReqInfo[iReq].bbox.minx + dfCellSizeX * 0.5 );
-            fprintf(fp, "%.12f\n", 
-                    pasReqInfo[iReq].bbox.maxy + dfCellSizeY * 0.5 );
-            fclose(fp);
+            char world_text[5000];
 
+            sprintf( world_text, "%.12f\n0\n0\n%.12f\n%.12f\n%.12f\n",
+                     dfCellSizeX, 
+                     dfCellSizeY,
+                     pasReqInfo[iReq].bbox.minx + dfCellSizeX * 0.5,
+                     pasReqInfo[iReq].bbox.maxy + dfCellSizeY * 0.5 );
+
+            VSIFWriteL( world_text, 1, strlen(world_text), fp );
+            VSIFCloseL( fp );
+
             /* GDAL should be called to reproject automatically. */
             if (msDrawLayer(map, lp, img) != 0)
                 status = MS_FAILURE;
 
             if (!lp->debug)
-                unlink(wldfile);
+                VSIUnlink( wldfile );
         }
         else
         {
@@ -1545,7 +1586,7 @@
 
     /* We're done with the remote server's response... delete it. */
     if (!lp->debug)
-      unlink(lp->data);
+        VSIUnlink(lp->data);
 
     /* restore prveious type */
     lp->type = currenttype;



More information about the mapserver-commits mailing list