[mapguide-commits] r7273 - in sandbox/jng/streaming: Common/Foundation/System Web/src/HttpHandler Web/src/IsapiAgent Web/src/MapAgentCommon

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Sun Dec 16 21:40:37 PST 2012


Author: jng
Date: 2012-12-16 21:40:35 -0800 (Sun, 16 Dec 2012)
New Revision: 7273

Added:
   sandbox/jng/streaming/Web/src/IsapiAgent/IsapiReaderStreamer.cpp
   sandbox/jng/streaming/Web/src/IsapiAgent/IsapiReaderStreamer.h
Modified:
   sandbox/jng/streaming/Common/Foundation/System/Util.cpp
   sandbox/jng/streaming/Common/Foundation/System/Util.h
   sandbox/jng/streaming/Web/src/HttpHandler/HttpReaderStreamer.cpp
   sandbox/jng/streaming/Web/src/HttpHandler/HttpReaderStreamer.h
   sandbox/jng/streaming/Web/src/IsapiAgent/IsapiAgent.vcxproj
   sandbox/jng/streaming/Web/src/IsapiAgent/IsapiResponseHandler.cpp
   sandbox/jng/streaming/Web/src/MapAgentCommon/MapAgentStrings.cpp
Log:
#2194: Add ISAPI implementation of MgHttpReaderStreamer. Chunking via ISAPI is more verbose than how it's done in Apache so a new EndStream() method has been added to MgHttpReaderStreamer which the ISAPI implementation uses to write the chunked response trailer. The default implementation does nothing. 

The observed memory spikes of the original implementation also can no longer be seen in this ISAPI handler. However for some reason, browser-initiated queries from the mapagent test pages do not show up as chunked responses. Not sure if IIS is messing with response headers. More investigation required.

Modified: sandbox/jng/streaming/Common/Foundation/System/Util.cpp
===================================================================
--- sandbox/jng/streaming/Common/Foundation/System/Util.cpp	2012-12-17 02:59:41 UTC (rev 7272)
+++ sandbox/jng/streaming/Common/Foundation/System/Util.cpp	2012-12-17 05:40:35 UTC (rev 7273)
@@ -1012,6 +1012,14 @@
     str = &buf[0];
 }
 
+void MgUtil::Int32ToHexString(INT32 val, string& str)
+{
+    char buf[32] = { 0 };
+
+    ::sprintf(buf, "%x", val);
+    str = &buf[0];
+}
+
 void MgUtil::UInt32ToString(UINT32 val, string& str)
 {
     char buf[32] = { 0 };

Modified: sandbox/jng/streaming/Common/Foundation/System/Util.h
===================================================================
--- sandbox/jng/streaming/Common/Foundation/System/Util.h	2012-12-17 02:59:41 UTC (rev 7272)
+++ sandbox/jng/streaming/Common/Foundation/System/Util.h	2012-12-17 05:40:35 UTC (rev 7273)
@@ -542,6 +542,7 @@
 
     static void Int32ToString(INT32 val, string& str);
     static void Int32ToString(INT32 val, STRING& str);
+    static void Int32ToHexString(INT32 val, string& str);
     static void UInt32ToString(UINT32 val, string& str);
     static void UInt32ToString(UINT32 val, STRING& str);
     static void Int64ToString(INT64 val, string& str);

Modified: sandbox/jng/streaming/Web/src/HttpHandler/HttpReaderStreamer.cpp
===================================================================
--- sandbox/jng/streaming/Web/src/HttpHandler/HttpReaderStreamer.cpp	2012-12-17 02:59:41 UTC (rev 7272)
+++ sandbox/jng/streaming/Web/src/HttpHandler/HttpReaderStreamer.cpp	2012-12-17 05:40:35 UTC (rev 7273)
@@ -22,6 +22,8 @@
 
 }
 
+void MgHttpReaderStreamer::EndStream() { }
+
 void MgHttpReaderStreamer::StreamResult()
 {
     MG_TRY()

Modified: sandbox/jng/streaming/Web/src/HttpHandler/HttpReaderStreamer.h
===================================================================
--- sandbox/jng/streaming/Web/src/HttpHandler/HttpReaderStreamer.h	2012-12-17 02:59:41 UTC (rev 7272)
+++ sandbox/jng/streaming/Web/src/HttpHandler/HttpReaderStreamer.h	2012-12-17 05:40:35 UTC (rev 7273)
@@ -32,6 +32,7 @@
     virtual void SetChunkedEncoding();
     virtual void WriteChunk(const char* str, size_t length);
     virtual void Dispose() { delete this; }
+    virtual void EndStream();
     
 private:
     void ToJson(string& xmlString, string& jsonString);

Modified: sandbox/jng/streaming/Web/src/IsapiAgent/IsapiAgent.vcxproj
===================================================================
--- sandbox/jng/streaming/Web/src/IsapiAgent/IsapiAgent.vcxproj	2012-12-17 02:59:41 UTC (rev 7272)
+++ sandbox/jng/streaming/Web/src/IsapiAgent/IsapiAgent.vcxproj	2012-12-17 05:40:35 UTC (rev 7273)
@@ -186,6 +186,7 @@
   <ItemGroup>
     <ClCompile Include="IsapiAgent.cpp" />
     <ClCompile Include="IsapiPostParser.cpp" />
+    <ClCompile Include="IsapiReaderStreamer.cpp" />
     <ClCompile Include="IsapiResponseHandler.cpp" />
   </ItemGroup>
   <ItemGroup>
@@ -196,6 +197,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="IsapiPostParser.h" />
+    <ClInclude Include="IsapiReaderStreamer.h" />
     <ClInclude Include="IsapiResponseHandler.h" />
     <ClInclude Include="stdafx.h" />
   </ItemGroup>

Added: sandbox/jng/streaming/Web/src/IsapiAgent/IsapiReaderStreamer.cpp
===================================================================
--- sandbox/jng/streaming/Web/src/IsapiAgent/IsapiReaderStreamer.cpp	                        (rev 0)
+++ sandbox/jng/streaming/Web/src/IsapiAgent/IsapiReaderStreamer.cpp	2012-12-17 05:40:35 UTC (rev 7273)
@@ -0,0 +1,56 @@
+#include "MapGuideCommon.h"
+#include "HttpHandler.h"
+#include "IsapiReaderStreamer.h"
+#include "MapAgentStrings.h"
+
+IsapiReaderStreamer::IsapiReaderStreamer(EXTENSION_CONTROL_BLOCK* rec, const std::string& sResponseHeader, MgReader* reader, CREFSTRING format) :
+    MgHttpReaderStreamer(reader, format), 
+    m_pECB(rec), 
+    m_sResponseHeader(sResponseHeader), 
+    m_bEndOfStream(false)
+{
+    m_hexLen.reserve(32);
+}
+
+IsapiReaderStreamer::~IsapiReaderStreamer() 
+{
+    EndStream();
+}
+
+void IsapiReaderStreamer::EndStream()
+{
+    if (!m_bEndOfStream)
+    {
+        //Write end of chunked response
+        DWORD len = 5;
+        m_pECB->WriteClient(m_pECB->ConnID, "0\r\n\r\n", &len, 0);
+
+        m_bEndOfStream = true;
+    }
+}
+
+void IsapiReaderStreamer::SetChunkedEncoding() 
+{
+    m_sResponseHeader.append("Connection: Keep-Alive\r\n");
+    m_sResponseHeader.append("Transfer-Encoding: chunked\r\n");
+    m_sResponseHeader.append("\r\n");
+
+    DWORD dwHeaderSize = (DWORD)m_sResponseHeader.length();
+    m_pECB->ServerSupportFunction(m_pECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, NULL, &dwHeaderSize, (LPDWORD)m_sResponseHeader.c_str());
+}
+
+void IsapiReaderStreamer::WriteChunk(const char* str, size_t length)
+{
+    m_hexLen.clear();
+    MgUtil::Int32ToHexString(length, m_hexLen);
+    m_hexLen.append(MapAgentStrings::CrLf);
+
+    DWORD len = m_hexLen.size();
+    m_pECB->WriteClient(m_pECB->ConnID, (LPVOID)m_hexLen.data(), &len, 0);
+
+    len = (DWORD)length;
+    m_pECB->WriteClient(m_pECB->ConnID, (LPVOID)str, &len, 0);
+
+    len = 2;
+    m_pECB->WriteClient(m_pECB->ConnID, (LPVOID)MapAgentStrings::CrLf, &len, 0);
+}
\ No newline at end of file

Added: sandbox/jng/streaming/Web/src/IsapiAgent/IsapiReaderStreamer.h
===================================================================
--- sandbox/jng/streaming/Web/src/IsapiAgent/IsapiReaderStreamer.h	                        (rev 0)
+++ sandbox/jng/streaming/Web/src/IsapiAgent/IsapiReaderStreamer.h	2012-12-17 05:40:35 UTC (rev 7273)
@@ -0,0 +1,41 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#ifndef ISAPI_READER_STREAMER_H
+#define ISAPI_READER_STREAMER_H
+
+#include "HttpExt.h"
+#include "HttpHandler.h"
+
+class IsapiReaderStreamer : public MgHttpReaderStreamer
+{
+public:
+    IsapiReaderStreamer(EXTENSION_CONTROL_BLOCK* rec, const std::string& sResponseHeader, MgReader* reader, CREFSTRING format);
+    virtual ~IsapiReaderStreamer();
+
+protected:
+    virtual void SetChunkedEncoding();
+    virtual void WriteChunk(const char* str, size_t length);
+    virtual void EndStream();
+
+private:
+    EXTENSION_CONTROL_BLOCK *m_pECB;
+    std::string m_hexLen;
+    std::string m_sResponseHeader;
+    bool m_bEndOfStream;
+};
+
+#endif
\ No newline at end of file

Modified: sandbox/jng/streaming/Web/src/IsapiAgent/IsapiResponseHandler.cpp
===================================================================
--- sandbox/jng/streaming/Web/src/IsapiAgent/IsapiResponseHandler.cpp	2012-12-17 02:59:41 UTC (rev 7272)
+++ sandbox/jng/streaming/Web/src/IsapiAgent/IsapiResponseHandler.cpp	2012-12-17 05:40:35 UTC (rev 7273)
@@ -19,6 +19,7 @@
 #include "HttpHandler.h"
 #include "HttpPrimitiveValue.h"
 #include "IsapiResponseHandler.h"
+#include "IsapiReaderStreamer.h"
 #include "MapAgentStrings.h"
 
 #include <stdlib.h>
@@ -102,6 +103,7 @@
             sResponseHeader.append(tempHeader);
         }
 
+        Ptr<MgReader> outputDataReader;
         Ptr<MgByteReader> outputReader;
         Ptr<MgDisposable> resultObj = result->GetResultObject();
         MgDisposable* pResultObj = (MgDisposable*)resultObj;
@@ -112,7 +114,7 @@
         }
         else if (NULL != dynamic_cast<MgFeatureReader*>(pResultObj))
         {
-            outputReader = ((MgFeatureReader*)pResultObj)->ToXml();
+            outputDataReader = SAFE_ADDREF((MgFeatureReader*)pResultObj); //Need to AddRef because there's now 2 references on this pointer
         }
         else if (NULL != dynamic_cast<MgStringCollection*>(pResultObj))
         {
@@ -120,11 +122,11 @@
         }
         else if (NULL != dynamic_cast<MgSqlDataReader*>(pResultObj))
         {
-            outputReader = ((MgSqlDataReader*)pResultObj)->ToXml();
+            outputDataReader = SAFE_ADDREF((MgSqlDataReader*)pResultObj); //Need to AddRef because there's now 2 references on this pointer
         }
         else if (NULL != dynamic_cast<MgDataReader*>(pResultObj))
         {
-            outputReader = ((MgDataReader*)pResultObj)->ToXml();
+            outputDataReader = SAFE_ADDREF((MgDataReader*)pResultObj); //Need to AddRef because there's now 2 references on this pointer
         }
         else if (NULL != dynamic_cast<MgSpatialContextReader*>(pResultObj))
         {
@@ -151,6 +153,11 @@
             DWORD dwBufLen = (DWORD)utf8.length();
             m_pECB->WriteClient(m_pECB->ConnID, (LPVOID)utf8.c_str(), &dwBufLen, 0);
         }
+        else if (outputDataReader != NULL)
+        {
+            IsapiReaderStreamer irs(m_pECB, sResponseHeader, outputDataReader, result->GetResultContentType());
+            irs.StreamResult();
+        }
         else if (outputReader != NULL)
         {
             INT64 outLen = outputReader->GetLength();

Modified: sandbox/jng/streaming/Web/src/MapAgentCommon/MapAgentStrings.cpp
===================================================================
--- sandbox/jng/streaming/Web/src/MapAgentCommon/MapAgentStrings.cpp	2012-12-17 02:59:41 UTC (rev 7272)
+++ sandbox/jng/streaming/Web/src/MapAgentCommon/MapAgentStrings.cpp	2012-12-17 05:40:35 UTC (rev 7273)
@@ -64,7 +64,6 @@
 const char* MapAgentStrings::WWWAuthKey = "WWW-Authenticate";
 const char* MapAgentStrings::WWWAuthVal = "Basic realm=\"%s\"";
 
-
 const wchar_t* MapAgentStrings::WebConfig = L"../webconfig.ini";
 const wchar_t* MapAgentStrings::FailedAuth1 = L"MgAuthenticationFailedException";
 const wchar_t* MapAgentStrings::FailedAuth2 = L"MgUnauthorizedAccessException";



More information about the mapguide-commits mailing list