Skip to content

Commit

Permalink
Merge pull request #376 from Azure/master
Browse files Browse the repository at this point in the history
Fix #367 & Support IdlePageOut
  • Loading branch information
rramachand21 committed Sep 10, 2014
2 parents ca16eff + b6c5e20 commit 5ea2056
Show file tree
Hide file tree
Showing 19 changed files with 367 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/config/iisnode_dev_x64.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="promoteServerVars" type="string" defaultValue=""/>
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
</sectionSchema>
</configSchema>
1 change: 1 addition & 0 deletions src/config/iisnode_dev_x86_on_x64.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="promoteServerVars" type="string" defaultValue=""/>
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
</sectionSchema>
</configSchema>
1 change: 1 addition & 0 deletions src/config/iisnode_dev_x86_on_x86.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="promoteServerVars" type="string" defaultValue=""/>
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
</sectionSchema>
</configSchema>
1 change: 1 addition & 0 deletions src/config/iisnode_express_schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="promoteServerVars" type="string" defaultValue=""/>
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
</sectionSchema>
</configSchema>
1 change: 1 addition & 0 deletions src/config/iisnode_express_schema_x64.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="promoteServerVars" type="string" defaultValue=""/>
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
</sectionSchema>
</configSchema>
1 change: 1 addition & 0 deletions src/config/iisnode_schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="promoteServerVars" type="string" defaultValue=""/>
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
</sectionSchema>
</configSchema>
1 change: 1 addition & 0 deletions src/config/iisnode_schema_x64.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
<attribute name="promoteServerVars" type="string" defaultValue=""/>
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
</sectionSchema>
</configSchema>
13 changes: 12 additions & 1 deletion src/iisnode/cmoduleconfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ CModuleConfiguration::CModuleConfiguration()
debuggerVirtualDirLength(0),
debuggerVirtualDirPhysicalPath(NULL),
recycleSignalEnabled(FALSE),
debuggerExtensionDll(NULL)
debuggerExtensionDll(NULL),
idlePageOutTimePeriod(0)
{
InitializeSRWLock(&this->srwlock);
}
Expand Down Expand Up @@ -865,6 +866,10 @@ HRESULT CModuleConfiguration::ApplyConfigOverrideKeyValue(IHttpContext* context,
{
CheckError(GetString(valueStart, &config->interceptor, TRUE));
}
else if(0 == stricmp(keyStart, "idlePageOutTimePeriod"))
{
CheckError(GetDWORD(valueStart, &config->idlePageOutTimePeriod));
}

return S_OK;
Error:
Expand Down Expand Up @@ -1223,6 +1228,7 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat
CheckError(GetString(section, L"configOverrides", &c->configOverrides));
CheckError(GetString(section, L"nodeProcessCommandLine", &c->nodeProcessCommandLine));
CheckError(GetString(section, L"interceptor", &c->interceptor));
CheckError(GetDWORD(section, L"idlePageOutTimePeriod", &c->idlePageOutTimePeriod));

// debuggerPathSegment

Expand Down Expand Up @@ -1299,6 +1305,11 @@ LPWSTR CModuleConfiguration::GetNodeProcessCommandLine(IHttpContext* ctx)
GETCONFIG(nodeProcessCommandLine)
}

DWORD CModuleConfiguration::GetIdlePageOutTimePeriod(IHttpContext* ctx)
{
GETCONFIG(idlePageOutTimePeriod)
}

LPWSTR CModuleConfiguration::GetInterceptor(IHttpContext* ctx)
{
GETCONFIG(interceptor)
Expand Down
2 changes: 2 additions & 0 deletions src/iisnode/cmoduleconfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class CModuleConfiguration : public IHttpStoredContext
DWORD maxLogFiles;
BOOL loggingEnabled;
BOOL debuggingEnabled;
DWORD idlePageOutTimePeriod;
PWSTR debuggerExtensionDll;
BOOL debugHeaderEnabled;
BOOL recycleSignalEnabled;
Expand Down Expand Up @@ -90,6 +91,7 @@ class CModuleConfiguration : public IHttpStoredContext

static HRESULT GetConfig(IHttpContext* context, CModuleConfiguration** config);

static DWORD GetIdlePageOutTimePeriod(IHttpContext* ctx);
static DWORD GetAsyncCompletionThreadCount(IHttpContext* ctx);
static DWORD GetNodeProcessCountPerApplication(IHttpContext* ctx);
static LPWSTR GetNodeProcessCommandLine(IHttpContext* ctx);
Expand Down
76 changes: 75 additions & 1 deletion src/iisnode/cnodeapplication.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,50 @@
#include "precomp.h"

volatile DWORD CNodeApplication::dwInternalAppId = 0;

CNodeApplication::CNodeApplication(CNodeApplicationManager* applicationManager, BOOL isDebugger, NodeDebugCommand debugCommand, DWORD debugPort)
: applicationManager(applicationManager), scriptName(NULL), processManager(NULL),
isDebugger(isDebugger), peerApplication(NULL), debugCommand(debugCommand),
debugPort(debugPort), needsRecycling(FALSE), configPath(NULL)
debugPort(debugPort), needsRecycling(FALSE), configPath(NULL), pIdleTimer(NULL),
fIdleCallbackInProgress(FALSE), fRequestsProcessedInLastIdleTimeoutPeriod(FALSE),
fEmptyWorkingSetAtStart(FALSE), dwIdlePageOutTimePeriod(0)
{
}

VOID
CALLBACK
CNodeApplication::IdleTimerCallback(
IN PTP_CALLBACK_INSTANCE Instance,
IN PVOID Context,
IN PTP_TIMER Timer
)
{
CNodeApplication* pApplication = (CNodeApplication*) Context;
if(pApplication != NULL)
{
if(!pApplication->fIdleCallbackInProgress)
{
pApplication->fIdleCallbackInProgress = TRUE;

if(!pApplication->fRequestsProcessedInLastIdleTimeoutPeriod || !pApplication->fEmptyWorkingSetAtStart)
{
pApplication->fEmptyWorkingSetAtStart = TRUE;
pApplication->EmptyWorkingSet();
if( pApplication->fEmptyW3WPWorkingSet )
{
SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1);
}
}

pApplication->fRequestsProcessedInLastIdleTimeoutPeriod = FALSE;

if(pApplication->pIdleTimer != NULL)
{
pApplication->pIdleTimer->SetTimer(pApplication->dwIdlePageOutTimePeriod, 0);
}
}
pApplication->fIdleCallbackInProgress = FALSE;
}
}

CNodeApplication::~CNodeApplication()
Expand All @@ -14,6 +54,13 @@ CNodeApplication::~CNodeApplication()

void CNodeApplication::Cleanup()
{
if(this->pIdleTimer != NULL)
{
this->pIdleTimer->CancelTimer();
delete this->pIdleTimer;
this->pIdleTimer = NULL;
}

this->GetApplicationManager()->GetFileWatcher()->RemoveWatch(this);

if (NULL != this->scriptName)
Expand Down Expand Up @@ -41,6 +88,26 @@ HRESULT CNodeApplication::Initialize(PCWSTR scriptName, IHttpContext* context)

CheckNull(scriptName);

if(CModuleConfiguration::GetIdlePageOutTimePeriod(context) > 0)
{
dwIdlePageOutTimePeriod = CModuleConfiguration::GetIdlePageOutTimePeriod(context);
if(dwInternalAppId == 0)
{
dwInternalAppId ++;
this->fEmptyW3WPWorkingSet = TRUE;
}
if(pIdleTimer == NULL)
{
pIdleTimer = new STTIMER;
ErrorIf(pIdleTimer == NULL, E_OUTOFMEMORY);
CheckError(pIdleTimer->InitializeTimer( CNodeApplication::IdleTimerCallback, this, 10000, 0));
}
else
{
pIdleTimer->SetTimer(10000, 0);
}
}

DWORD len = wcslen(scriptName) + 1;
ErrorIf(NULL == (this->scriptName = new WCHAR[len]), ERROR_NOT_ENOUGH_MEMORY);
wcscpy(this->scriptName, scriptName);
Expand Down Expand Up @@ -74,6 +141,11 @@ PCWSTR CNodeApplication::GetConfigPath()
return this->configPath;
}

HRESULT CNodeApplication::EmptyWorkingSet()
{
return this->processManager->EmptyWorkingSet();
}

HRESULT CNodeApplication::SetConfigPath(IHttpContext * context)
{
HRESULT hr = S_OK;
Expand Down Expand Up @@ -109,6 +181,8 @@ HRESULT CNodeApplication::Dispatch(IHttpContext* context, IHttpEventProvider* pP
CheckNull(context);
CheckNull(pProvider);

fRequestsProcessedInLastIdleTimeoutPeriod = TRUE;

ErrorIf(NULL == (*ctx = new CNodeHttpStoredContext(this, this->GetApplicationManager()->GetEventProvider(), context)), ERROR_NOT_ENOUGH_MEMORY);
IHttpModuleContextContainer* moduleContextContainer = context->GetModuleContextContainer();
moduleContextContainer->SetModuleContext(*ctx, this->GetApplicationManager()->GetModuleId());
Expand Down
17 changes: 17 additions & 0 deletions src/iisnode/cnodeapplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class CNodeApplication
{
private:

volatile static DWORD dwInternalAppId;
PWSTR scriptName;
PWSTR configPath;
CNodeApplicationManager* applicationManager;
Expand All @@ -19,6 +20,12 @@ class CNodeApplication
NodeDebugCommand debugCommand;
DWORD debugPort;
BOOL needsRecycling;
STTIMER *pIdleTimer;
BOOL fIdleCallbackInProgress;
BOOL fRequestsProcessedInLastIdleTimeoutPeriod;
BOOL fEmptyW3WPWorkingSet; // flag to indicate that this application is responsible for emptying w3wp working set (only one app should be responsible).
BOOL fEmptyWorkingSetAtStart;
volatile DWORD dwIdlePageOutTimePeriod;

void Cleanup();

Expand All @@ -27,6 +34,16 @@ class CNodeApplication
CNodeApplication(CNodeApplicationManager* applicationManager, BOOL isDebugger, NodeDebugCommand debugCommand, DWORD debugPort);
~CNodeApplication();

static
VOID
CALLBACK
IdleTimerCallback(
IN PTP_CALLBACK_INSTANCE Instance,
IN PVOID Context,
IN PTP_TIMER Timer
);

HRESULT EmptyWorkingSet();
HRESULT Initialize(PCWSTR scriptName, IHttpContext* context);
PCWSTR GetScriptName();
PCWSTR GetConfigPath();
Expand Down
1 change: 0 additions & 1 deletion src/iisnode/cnodeapplicationmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ class CNodeApplicationManager

CNodeApplicationManager(IHttpServer* server, HTTP_MODULE_ID moduleId);
~CNodeApplicationManager();

IHttpServer* GetHttpServer();
HTTP_MODULE_ID GetModuleId();
CAsyncManager* GetAsyncManager();
Expand Down
1 change: 0 additions & 1 deletion src/iisnode/cnodehttpmodulefactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ class CNodeHttpModuleFactory : public IHttpModuleFactory
{
CNodeApplicationManager* applicationManager;


public:

CNodeHttpModuleFactory();
Expand Down
17 changes: 17 additions & 0 deletions src/iisnode/cnodeprocessmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ CNodeApplication* CNodeProcessManager::GetApplication()
return this->application;
}

HRESULT CNodeProcessManager::EmptyWorkingSet()
{
ENTER_SRW_EXCLUSIVE(this->srwlock)

for (int i = 0; i < this->processCount; i++)
{
if(this->processes[i] != NULL && !this->processes[i]->HasProcessExited())
{
SetProcessWorkingSetSize(this->processes[i]->GetProcess(), -1, -1);
}
}

LEAVE_SRW_EXCLUSIVE(this->srwlock)

return S_OK;
}

HRESULT CNodeProcessManager::Initialize(IHttpContext* context)
{
HRESULT hr;
Expand Down
1 change: 1 addition & 0 deletions src/iisnode/cnodeprocessmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class CNodeProcessManager
CNodeProcessManager(CNodeApplication* application, IHttpContext* context);
~CNodeProcessManager();

HRESULT EmptyWorkingSet();
CNodeApplication* GetApplication();
HRESULT Initialize(IHttpContext* context);
HRESULT RecycleProcess(CNodeProcess* process);
Expand Down
6 changes: 5 additions & 1 deletion src/iisnode/cprotocolbridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,11 @@ void CProtocolBridge::SendHttpRequestHeaders(CNodeHttpStoredContext* context)
// to enable named pipe connection pooling

request = context->GetHttpContext()->GetRequest();
CheckError(request->SetHeader(HttpHeaderConnection, "keep-alive", 10, TRUE));

if(stricmp(request->GetHeader(HttpHeaderConnection), "upgrade") != 0)
{
CheckError(request->SetHeader(HttpHeaderConnection, "keep-alive", 10, TRUE));
}

// Expect: 100-continue has been processed by IIS - do not propagate it up to node.js since node will
// attempt to process it again
Expand Down
1 change: 1 addition & 0 deletions src/iisnode/precomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
// Project header files
#include "errors.h"
#include "utils.h"
#include "sttimer.h"
#include "cconnectionpool.h"
#include "cnodeeventprovider.h"
#include "cnodeconstants.h"
Expand Down
Loading

0 comments on commit 5ea2056

Please sign in to comment.