source: trunk/MgDev/Server/src/Common/Manager/ServerManager.cpp

Last change on this file was 9971, checked in by jng, 3 years ago

Merged revision(s) 9743-9755 from sandbox/jng/flatten_exceptions:
Remove all exceptions in Foundation and modify all throws to throw MgException, passing an exception code instead.
........
Remove all exceptions in Geometry/CoordinateSystem and modify all throws to throw MgException, passing an exception code instead.
........
Remove all exceptions in PlatformBase and modify all throws to throw MgException, passing an exception code instead.
........
Remove all exceptions in MapGuideCommon and modify all throws to throw MgException, passing an exception code instead.
........
Remove all exceptions from the rest of the server tier and modify all throws to throw MgException, passing an exception code instead.
........
Remove all exceptions from the rest of the web tier and modify all throws to throw MgException, passing an exception code instead. Remove all non-MgException classes from SWIG config files. Add MgExceptionCodes to SWIG constants files.
........
Remove all exceptions from mg-desktop and modify all throws to throw MgException, passing an exception code instead. Remove all non-MgException classes from SWIG config files. Add MgExceptionCodes to SWIG constants files.
........
Fix linux build
........
Fix up mg-desktop unit test runner
........
Fix APi doc for GetNativeErrorCode
........
Disable site manager tests wholesale until further notice
........
Fix up MgException handling in downstream api consumers / test code.
........
Fix incorrect operator
........

  • Property svn:eol-style set to native
File size: 53.2 KB
Line 
1//
2// Copyright (C) 2004-2011 by Autodesk, Inc.
3//
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of version 2.1 of the GNU Lesser
6// General Public License as published by the Free Software Foundation.
7//
8// This library is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11// Lesser General Public License for more details.
12//
13// You should have received a copy of the GNU Lesser General Public
14// License along with this library; if not, write to the Free Software
15// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16//
17
18#include "ServerManager.h"
19#include "ProductVersion.h"
20#include "ServiceManager.h"
21#include "UnmanagedDataManager.h"
22#include "ServerFeatureService.h"
23#include "WorkerThread.h"
24#include "WorkerThreadData.h"
25
26#ifdef _WIN32
27#include <Psapi.h>
28#else
29#include <sys/time.h>
30#include <sys/resource.h>
31#include <unistd.h>
32#endif
33
34const STRING MgServerManager::DocumentExtension = L".awd";
35const STRING MgServerManager::DocumentPath = L"DocumentPath";
36
37// Process-wide MgServerManager
38Ptr<MgServerManager> MgServerManager::m_serverManager = (MgServerManager*)NULL;
39
40// Constructor
41MgServerManager::MgServerManager() :
42 m_pClientHandles(NULL),
43 m_ssServerStatus(MgServerManager::ssOffline),
44 m_isSiteServer(true),
45 m_totalOperationTime(0),
46 m_totalReceivedOperations(0),
47 m_totalProcessedOperations(0),
48 m_totalConnections(0),
49 m_totalActiveConnections(0),
50 m_pAdminMessageQueue(NULL),
51 m_pClientMessageQueue(NULL),
52 m_pSiteMessageQueue(NULL),
53 m_pWorkerThreads(NULL)
54{
55 m_localServerAddress = MgConfigProperties::DefaultGeneralPropertyMachineIp;
56 m_defaultMessageLocale = MgConfigProperties::DefaultGeneralPropertyDefaultMessageLocale;
57 m_displayName = MgConfigProperties::DefaultGeneralPropertyDisplayName;
58
59 // Admin
60 m_nAdminPort = MgConfigProperties::DefaultAdministrativeConnectionPropertyPort;
61 m_adminEmail = MgConfigProperties::DefaultAdministrativeConnectionPropertyEmail;
62 m_nAdminThreads = MgConfigProperties::DefaultAdministrativeConnectionPropertyThreadPoolSize;
63
64 // Client
65 m_nClientPort = MgConfigProperties::DefaultClientConnectionPropertyPort;
66 m_nClientThreads = MgConfigProperties::DefaultClientConnectionPropertyThreadPoolSize;
67
68 // Site
69 m_siteServerAddress = MgConfigProperties::DefaultSiteConnectionPropertyIpAddress;
70 m_nSitePort = MgConfigProperties::DefaultSiteConnectionPropertyPort;
71 m_nSiteThreads = MgConfigProperties::DefaultSiteConnectionPropertyThreadPoolSize;
72
73 m_startTime = ACE_OS::gettimeofday();
74}
75
76// Destructor
77MgServerManager::~MgServerManager()
78{
79 ACE_DEBUG ((LM_DEBUG, ACE_TEXT("(%t) MgServerManager::~MgServerManager()\n")));
80
81 // Remove client handlers
82 if(m_pClientHandles)
83 {
84 ACE_Reactor_Mask mask = ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL;
85 ACE_Unbounded_Set_Iterator<ACE_HANDLE> handleIter(*m_pClientHandles);
86 for (handleIter = m_pClientHandles->begin(); handleIter != m_pClientHandles->end(); handleIter++)
87 {
88 ACE_HANDLE handle = (*handleIter);
89 if ( ACE_Reactor::instance()->remove_handler(handle, mask) == 0 )
90 {
91 m_pClientHandles->remove(handle);
92 }
93 }
94
95 delete m_pClientHandles;
96 m_pClientHandles = NULL;
97 }
98
99 delete m_pWorkerThreads;
100 m_pWorkerThreads = NULL;
101}
102
103void MgServerManager::Dispose()
104{
105 delete this;
106}
107
108// Get pointer to a process-wide MgServerManager.
109MgServerManager* MgServerManager::GetInstance()
110{
111 MG_TRY()
112
113 ACE_TRACE ("MgServerManager::GetInstance");
114
115 if (MgServerManager::m_serverManager == NULL)
116 {
117 // Perform Double-Checked Locking Optimization.
118 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, *ACE_Static_Object_Lock::instance (), 0));
119 if (MgServerManager::m_serverManager == NULL)
120 {
121 MgServerManager::m_serverManager = new MgServerManager;
122 }
123 }
124
125 MG_CATCH_AND_THROW(L"MgServerManager.GetInstance")
126
127 // To avoid overheads and maintain thread safety,
128 // do not assign this returned static singleton to a Ptr object.
129 return MgServerManager::m_serverManager;
130}
131
132// Initialization the server manager
133void MgServerManager::Initialize(CREFSTRING locale)
134{
135 MG_TRY()
136
137 MG_LOG_TRACE_ENTRY(L"MgServerManager::Initialize()");
138
139 // Set the message locale
140 m_defaultMessageLocale = locale;
141
142 m_pClientHandles = new ACE_Unbounded_Set<ACE_HANDLE>;
143
144 // Load the configuration properties
145 LoadConfigurationProperties();
146
147 MgConfiguration* pConfiguration = MgConfiguration::GetInstance();
148
149 // Determine if this server is a site or support server.
150 pConfiguration->GetBoolValue(
151 MgConfigProperties::HostPropertiesSection,
152 MgConfigProperties::HostPropertySiteService,
153 m_isSiteServer,
154 MgConfigProperties::DefaultHostPropertySiteService);
155
156 // Admin Connection
157 pConfiguration->GetIntValue(MgConfigProperties::AdministrativeConnectionPropertiesSection, MgConfigProperties::AdministrativeConnectionPropertyPort, m_nAdminPort, MgConfigProperties::DefaultAdministrativeConnectionPropertyPort);
158 pConfiguration->GetIntValue(MgConfigProperties::AdministrativeConnectionPropertiesSection, MgConfigProperties::AdministrativeConnectionPropertyThreadPoolSize, m_nAdminThreads, MgConfigProperties::DefaultAdministrativeConnectionPropertyThreadPoolSize);
159
160 // Client Connection
161 pConfiguration->GetIntValue(MgConfigProperties::ClientConnectionPropertiesSection, MgConfigProperties::ClientConnectionPropertyPort, m_nClientPort, MgConfigProperties::DefaultClientConnectionPropertyPort);
162 pConfiguration->GetIntValue(MgConfigProperties::ClientConnectionPropertiesSection, MgConfigProperties::ClientConnectionPropertyThreadPoolSize, m_nClientThreads, MgConfigProperties::DefaultClientConnectionPropertyThreadPoolSize);
163
164 // Site Connection
165 pConfiguration->GetIntValue(MgConfigProperties::SiteConnectionPropertiesSection, MgConfigProperties::SiteConnectionPropertyPort, m_nSitePort, MgConfigProperties::DefaultSiteConnectionPropertyPort);
166 pConfiguration->GetIntValue(MgConfigProperties::SiteConnectionPropertiesSection, MgConfigProperties::SiteConnectionPropertyThreadPoolSize, m_nSiteThreads, MgConfigProperties::DefaultSiteConnectionPropertyThreadPoolSize);
167
168 // Validate IP configurations for this server.
169 STRING localServerAddress, siteServerAddress;
170
171 pConfiguration->GetStringValue(
172 MgConfigProperties::GeneralPropertiesSection,
173 MgConfigProperties::GeneralPropertyMachineIp,
174 localServerAddress,
175 MgConfigProperties::DefaultGeneralPropertyMachineIp);
176 pConfiguration->GetStringValue(
177 MgConfigProperties::SiteConnectionPropertiesSection,
178 MgConfigProperties::SiteConnectionPropertyIpAddress,
179 siteServerAddress,
180 MgConfigProperties::DefaultSiteConnectionPropertyIpAddress);
181
182 MgIpUtil::HostNameToAddress(localServerAddress, m_localServerAddress);
183 MgIpUtil::HostNameToAddress(siteServerAddress, m_siteServerAddress);
184
185 if (m_isSiteServer)
186 {
187/* // Uncomment the following check if we need to validate the local server address.
188 // For now, just use whatever was input by the user.
189 if (!MgIpUtil::IsLocalHost(m_localServerAddress))
190 {
191 MgStringCollection arguments;
192 arguments.Add(localServerAddress);
193
194 throw new MgException(MgExceptionCodes::MgInvalidIpAddressException,
195 L"MgServerManager.Initialize", __LINE__, __WFILE__, &arguments,
196 L"MgMachineIpMustBeLocalHost", NULL);
197 }
198*/
199 if (0 != _wcsicmp(m_siteServerAddress.c_str(), m_localServerAddress.c_str()))
200 {
201 MgStringCollection arguments;
202 arguments.Add(siteServerAddress);
203 arguments.Add(localServerAddress);
204
205 throw new MgException(MgExceptionCodes::MgLogicException,
206 L"MgServerManager.Initialize", __LINE__, __WFILE__, NULL,
207 L"MgInvalidIpConfigurationForSiteServer", &arguments);
208 }
209 }
210 else
211 {
212 if (MgIpUtil::IsLocalHost(m_siteServerAddress))
213 {
214 MgStringCollection arguments;
215 arguments.Add(siteServerAddress);
216
217 throw new MgException(MgExceptionCodes::MgInvalidIpAddressException,
218 L"MgServerManager.Initialize", __LINE__, __WFILE__, &arguments,
219 L"MgSiteServerIpMustNotBeLocalHost", NULL);
220 }
221
222 if (0 == _wcsicmp(m_siteServerAddress.c_str(), m_localServerAddress.c_str()))
223 {
224 MgStringCollection arguments;
225 arguments.Add(siteServerAddress);
226 arguments.Add(localServerAddress);
227
228 throw new MgException(MgExceptionCodes::MgLogicException,
229 L"MgServerManager.Initialize", __LINE__, __WFILE__, NULL,
230 L"MgInvalidIpConfigurationForSupportServer", &arguments);
231 }
232 }
233
234 // Create the worker thread pool
235 INT32 workerThreadPoolSize = 0;
236 pConfiguration->GetIntValue(MgConfigProperties::GeneralPropertiesSection, MgConfigProperties::GeneralPropertyWorkerThreadPoolSize, workerThreadPoolSize, MgConfigProperties::DefaultGeneralPropertyWorkerThreadPoolSize);
237 m_pWorkerThreads = new MgWorkerThread(m_threadManager, workerThreadPoolSize);
238 m_pWorkerThreads->Activate();
239
240 MG_LOG_TRACE_ENTRY(L"MgServerManager::Initialize() - Site server's IP address: " + m_siteServerAddress);
241 MG_LOG_TRACE_ENTRY(L"MgServerManager::Initialize() - Local server's IP address: " + m_localServerAddress);
242
243 m_ssServerStatus = MgServerManager::ssOnline;
244
245 MG_CATCH_AND_THROW(L"MgServerManager.Initialize")
246}
247
248void MgServerManager::LoadConfigurationProperties()
249{
250 MG_LOGMANAGER_TRY()
251
252 MG_LOG_TRACE_ENTRY(L"MgServerManager::LoadConfigurationProperties()");
253
254 MgConfiguration* pConfiguration = MgConfiguration::GetInstance();
255
256 // General
257 pConfiguration->GetStringValue(MgConfigProperties::GeneralPropertiesSection, MgConfigProperties::GeneralPropertyDisplayName, m_displayName, MgConfigProperties::DefaultGeneralPropertyDisplayName);
258
259 // Admin Connection
260 pConfiguration->GetStringValue(MgConfigProperties::AdministrativeConnectionPropertiesSection, MgConfigProperties::AdministrativeConnectionPropertyEmail, m_adminEmail, MgConfigProperties::DefaultAdministrativeConnectionPropertyEmail);
261
262 MG_CATCH_AND_THROW(L"MgServerManager.LoadConfigurationProperties")
263}
264
265STRING MgServerManager::GetDefaultMessageLocale()
266{
267 return m_defaultMessageLocale;
268}
269
270///////////////////////////////////////////////////////////////////////////////////
271/// <summary>
272/// Gets the configuration properties for the specified property section.
273/// </summary>
274MgPropertyCollection* MgServerManager::GetConfigurationProperties(CREFSTRING propertySection)
275{
276 Ptr<MgPropertyCollection> pProperties;
277 pProperties = NULL;
278
279 MG_TRY()
280
281 MG_LOG_TRACE_ENTRY(L"MgServerManager::GetConfigurationProperties()");
282
283 MgConfiguration* pConfiguration = MgConfiguration::GetInstance();
284 CHECKNULL(pConfiguration, L"MgServerManager::GetConfigurationProperties");
285
286 // Retrieve the properties
287 pProperties = pConfiguration->GetProperties(propertySection);
288
289 MG_CATCH_AND_THROW(L"MgServerManager.GetConfigurationProperties")
290
291 return pProperties.Detach();
292}
293
294///////////////////////////////////////////////////////////////////////////////////
295/// <summary>
296/// Sets the configuration properties for the specified property section.
297/// </summary>
298void MgServerManager::SetConfigurationProperties(CREFSTRING propertySection,
299 MgPropertyCollection* properties)
300{
301 MG_TRY()
302
303 MG_LOG_TRACE_ENTRY(L"MgServerManager::SetConfigurationProperties()");
304
305 CHECKARGUMENTNULL(properties, L"MgServerManager.SetConfigurationProperties");
306
307 MgConfiguration* pConfiguration = MgConfiguration::GetInstance();
308
309 CHECKNULL(pConfiguration, L"MgServerManager.SetConfigurationProperties");
310
311 // Set the properties
312 pConfiguration->SetProperties(propertySection, properties);
313
314 // Enable/disable specified services for this local server if applicable.
315 if (MgConfigProperties::HostPropertiesSection == propertySection)
316 {
317 MgServiceManager* serviceManager = MgServiceManager::GetInstance();
318 assert(NULL != serviceManager);
319
320 serviceManager->EnableServices(properties);
321 }
322 // Refresh unmanaged data mappings.
323 else if (MgConfigProperties::UnmanagedDataMappingsSection == propertySection)
324 {
325 MgUnmanagedDataManager::GetInstance()->RefreshUnmanagedDataMappings();
326 }
327
328 // Certain properties can be updated without requiring a server restart
329 LoadConfigurationProperties();
330
331 MgLogManager* logManager = MgLogManager::GetInstance();
332 assert(NULL != logManager);
333 logManager->LoadConfigurationProperties();
334
335 MG_CATCH_AND_THROW(L"MgServerManager.SetConfigurationProperties")
336}
337
338///////////////////////////////////////////////////////////////////////////////////
339/// <summary>
340/// Removes the configuration properties for the specified property section.
341/// If the properties are not specified, then the entire section will be removed.
342/// </summary>
343void MgServerManager::RemoveConfigurationProperties(CREFSTRING propertySection,
344 MgPropertyCollection* properties)
345{
346 MG_TRY()
347
348 MG_LOG_TRACE_ENTRY(L"MgServerManager::RemoveConfigurationProperties()");
349
350 CHECKARGUMENTNULL(properties, L"MgServerManager.RemoveConfigurationProperties");
351
352 MgConfiguration* pConfiguration = MgConfiguration::GetInstance();
353
354 CHECKNULL(pConfiguration, L"MgServerManager.RemoveConfigurationProperties");
355
356 // Remove the properties.
357 pConfiguration->RemoveProperties(propertySection, properties);
358
359 // Enable/disable specified services for this local server if applicable.
360 if (MgConfigProperties::HostPropertiesSection == propertySection)
361 {
362 MgServiceManager* serviceManager = MgServiceManager::GetInstance();
363 assert(NULL != serviceManager);
364
365 serviceManager->EnableServices(properties);
366 }
367 // Refresh unmanaged data mappings.
368 else if (MgConfigProperties::UnmanagedDataMappingsSection == propertySection)
369 {
370 MgUnmanagedDataManager::GetInstance()->RefreshUnmanagedDataMappings();
371 }
372
373 // Certain properties can be updated without requiring a server restart
374 LoadConfigurationProperties();
375
376 MgLogManager* logManager = MgLogManager::GetInstance();
377 assert(NULL != logManager);
378 logManager->LoadConfigurationProperties();
379
380 MG_CATCH_AND_THROW(L"MgServerManager.RemoveConfigurationProperties")
381}
382
383
384///////////////////////////////////////////////////////////////////////////////////
385/// <summary>
386/// Gets the information properties for the server.
387/// </summary>
388MgPropertyCollection* MgServerManager::GetInformationProperties()
389{
390 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, *ACE_Static_Object_Lock::instance (), NULL));
391
392 Ptr<MgPropertyCollection> pProperties;
393 pProperties = NULL;
394
395 MG_TRY()
396
397 MG_LOG_TRACE_ENTRY(L"MgServerManager::GetInformationProperties()");
398
399 pProperties = new MgPropertyCollection();
400
401 // Add the information properties
402 Ptr<MgProperty> pProperty;
403
404 // Add the AdminOperationsQueueCount
405 int nOperationQueueCount = GetAdminOperationsQueueCount();
406 pProperty = new MgInt32Property(MgServerInformationProperties::AdminOperationsQueueCount, nOperationQueueCount);
407 pProperties->Add(pProperty);
408
409 // Add the ClientOperationsQueueCount
410 nOperationQueueCount = GetClientOperationsQueueCount();
411 pProperty = new MgInt32Property(MgServerInformationProperties::ClientOperationsQueueCount, nOperationQueueCount);
412 pProperties->Add(pProperty);
413
414 // Add the SiteOperationsQueueCount
415 nOperationQueueCount = GetSiteOperationsQueueCount();
416 pProperty = new MgInt32Property(MgServerInformationProperties::SiteOperationsQueueCount, nOperationQueueCount);
417 pProperties->Add(pProperty);
418
419 // Add the CpuUtilization
420#ifdef _WIN32
421 INT32 nCpuLoad = ComputeWIN32CpuLoad();
422#else
423 INT32 nCpuLoad = ComputeLinuxCpuLoad();
424#endif // _WIN32
425 pProperty = new MgInt32Property(MgServerInformationProperties::CpuUtilization, nCpuLoad);
426 pProperties->Add(pProperty);
427
428 // Add the Status
429 bool bOnline = IsOnline();
430 pProperty = new MgBooleanProperty(MgServerInformationProperties::Status, bOnline);
431 pProperties->Add(pProperty);
432
433 // Add the Uptime
434 INT64 nUptime = GetUptime();
435 pProperty = new MgInt64Property(MgServerInformationProperties::Uptime, nUptime);
436 pProperties->Add(pProperty);
437
438 // Add the TotalPhysicalMemory
439 INT64 nMemory = GetTotalPhysicalMemory();
440 pProperty = new MgInt64Property(MgServerInformationProperties::TotalPhysicalMemory, nMemory);
441 pProperties->Add(pProperty);
442
443 // Add the AvailablePhysicalMemory
444 nMemory = GetAvailablePhysicalMemory();
445 pProperty = new MgInt64Property(MgServerInformationProperties::AvailablePhysicalMemory, nMemory);
446 pProperties->Add(pProperty);
447
448 // Add the TotalVirtualMemory
449 nMemory = GetTotalVirtualMemory();
450 pProperty = new MgInt64Property(MgServerInformationProperties::TotalVirtualMemory, nMemory);
451 pProperties->Add(pProperty);
452
453 // Add the AvailableVirtualMemory
454 nMemory = GetAvailableVirtualMemory();
455 pProperty = new MgInt64Property(MgServerInformationProperties::AvailableVirtualMemory, nMemory);
456 pProperties->Add(pProperty);
457
458 // Add the TotalOperationTime
459 // This value needs to be returned in seconds according to the schema
460 INT64 nTotalOperationTime = GetTotalOperationTime() / 1000;
461 pProperty = new MgInt64Property(MgServerInformationProperties::TotalOperationTime, nTotalOperationTime);
462 pProperties->Add(pProperty);
463
464 // Add the AverageOperationTime
465 INT64 nAverageOperationTime = GetAverageOperationTime();
466 pProperty = new MgInt64Property(MgServerInformationProperties::AverageOperationTime, nAverageOperationTime);
467 pProperties->Add(pProperty);
468
469 // Add the server Version
470 pProperty = new MgStringProperty(MgServerInformationProperties::ServerVersion, ProductVersion);
471 pProperties->Add(pProperty);
472
473 // Add the DisplayName
474 pProperty = new MgStringProperty(MgServerInformationProperties::DisplayName, m_displayName);
475 pProperties->Add(pProperty);
476
477 // Add the MachineIp
478 pProperty = new MgStringProperty(MgServerInformationProperties::MachineIp, m_localServerAddress);
479 pProperties->Add(pProperty);
480
481 // Add the Operations info
482 INT32 nTotalReceivedOperations = GetTotalReceivedOperations();
483 pProperty = new MgInt32Property(MgServerInformationProperties::TotalReceivedOperations, nTotalReceivedOperations);
484 pProperties->Add(pProperty);
485
486 INT32 nTotalProcessedOperations = GetTotalProcessedOperations();
487 pProperty = new MgInt32Property(MgServerInformationProperties::TotalProcessedOperations, nTotalProcessedOperations);
488 pProperties->Add(pProperty);
489
490 // Add the Connection info
491 INT32 nTotalConnections = GetTotalConnections();
492 pProperty = new MgInt32Property(MgServerInformationProperties::TotalConnections, nTotalConnections);
493 pProperties->Add(pProperty);
494
495 INT32 nTotalActiveConnections = GetTotalActiveConnections();
496 pProperty = new MgInt32Property(MgServerInformationProperties::TotalActiveConnections, nTotalActiveConnections);
497 pProperties->Add(pProperty);
498
499 // Add the Operating System Version
500 STRING osVersion = GetOperatingSystemVersion();
501 pProperty = new MgStringProperty(MgServerInformationProperties::OperatingSystemVersion, osVersion);
502 pProperties->Add(pProperty);
503
504#ifdef _WIN32
505 HANDLE procHandle = GetCurrentProcess();
506 PROCESS_MEMORY_COUNTERS counters;
507 counters.cb = sizeof(counters);
508 BOOL ok = GetProcessMemoryInfo(procHandle, &counters, sizeof(counters));
509 if (ok)
510 {
511 pProperty = new MgInt64Property(MgServerInformationProperties::WorkingSet, counters.WorkingSetSize);
512 pProperties->Add(pProperty);
513 pProperty = new MgInt64Property(MgServerInformationProperties::VirtualMemory, counters.PagefileUsage);
514 pProperties->Add(pProperty);
515 }
516 else
517 {
518 // Failed to get required information
519 pProperty = new MgInt64Property(MgServerInformationProperties::WorkingSet, -1);
520 pProperties->Add(pProperty);
521 pProperty = new MgInt64Property(MgServerInformationProperties::VirtualMemory, -1);
522 pProperties->Add(pProperty);
523 }
524#else
525 // getrusage does not work on Linux so pull information directly
526 // from proc filesystem.
527 int pageSize = getpagesize();
528 char procName[256];
529 sprintf(procName,"/proc/%d/status",getpid());
530 FILE* fp = fopen(procName,"rb");
531 if (NULL != fp)
532 {
533 char buf[1024];
534 memset(buf,0,1024);
535 fread(buf, 1024, 1, fp);
536 fclose(fp);
537
538 char* strRss = "VmRSS:";
539 char* end = NULL;
540 char* loc = strstr(buf, strRss);
541 if (NULL != loc)
542 {
543 long kbytes = strtol(loc + strlen(strRss) + 1, &end, 10);
544 INT64 workingSet = kbytes * 1000;
545 pProperty = new MgInt64Property(MgServerInformationProperties::WorkingSet, workingSet);
546 pProperties->Add(pProperty);
547 }
548 else
549 {
550 // Failed to get required information
551 pProperty = new MgInt64Property(MgServerInformationProperties::WorkingSet, -1);
552 pProperties->Add(pProperty);
553 }
554
555 char* strSize = "VmSize:";
556 loc = strstr(buf, strSize);
557 if (NULL != loc)
558 {
559 long kbytes = strtol(loc + strlen(strSize) + 1, &end, 10);
560 INT64 virtualMemory = kbytes * 1000;
561 pProperty = new MgInt64Property(MgServerInformationProperties::VirtualMemory, virtualMemory);
562 pProperties->Add(pProperty);
563 }
564 else
565 {
566 // Failed to get required information
567 pProperty = new MgInt64Property(MgServerInformationProperties::VirtualMemory, -1);
568 pProperties->Add(pProperty);
569 }
570 }
571 else
572 {
573 // Failed to get required information
574 pProperty = new MgInt64Property(MgServerInformationProperties::WorkingSet, -1);
575 pProperties->Add(pProperty);
576 pProperty = new MgInt64Property(MgServerInformationProperties::VirtualMemory, -1);
577 pProperties->Add(pProperty);
578 }
579#endif
580
581 // Add cache information
582 MgCacheManager* cacheManager = MgCacheManager::GetInstance();
583 if(cacheManager)
584 {
585 MgFeatureServiceCache* fsCache = cacheManager->GetFeatureServiceCache();
586 INT32 fsCacheSize = fsCache->GetCacheSize();
587 INT32 fsCacheDroppedEntries = fsCache->GetDroppedEntriesCount();
588
589 pProperty = new MgInt32Property(MgServerInformationProperties::CacheSize, fsCacheSize);
590 pProperties->Add(pProperty);
591
592 pProperty = new MgInt32Property(MgServerInformationProperties::CacheDroppedEntries, fsCacheDroppedEntries);
593 pProperties->Add(pProperty);
594 }
595 else
596 {
597 // Failed to get required information
598 pProperty = new MgInt32Property(MgServerInformationProperties::CacheSize, -1);
599 pProperties->Add(pProperty);
600
601 pProperty = new MgInt32Property(MgServerInformationProperties::CacheDroppedEntries, -1);
602 pProperties->Add(pProperty);
603 }
604
605 MG_CATCH_AND_THROW(L"MgServerManager.GetInformationProperties")
606
607 return pProperties.Detach();
608}
609
610///////////////////////////////////////////////////////////////////////////////////
611/// <summary>
612/// Gets the site version.
613/// </summary>
614STRING MgServerManager::GetSiteVersion()
615{
616 return ProductVersion;
617}
618
619///////////////////////////////////////////////////////////////////////////////////
620/// <summary>
621/// Gets the status properties for the server.
622/// </summary>
623MgPropertyCollection* MgServerManager::GetSiteStatus()
624{
625 Ptr<MgPropertyCollection> pProperties;
626 pProperties = NULL;
627
628 MG_TRY()
629
630 MG_LOG_TRACE_ENTRY(L"MgServerManager::GetSiteStatus()");
631
632 pProperties = new MgPropertyCollection();
633
634 // Add the information properties
635 Ptr<MgProperty> pProperty;
636
637 // Add the DisplayName
638 pProperty = new MgStringProperty(MgServerInformationProperties::DisplayName, m_displayName);
639 pProperties->Add(pProperty);
640
641 // Add the Status
642 bool bOnline = IsOnline();
643 pProperty = new MgBooleanProperty(MgServerInformationProperties::Status, bOnline);
644 pProperties->Add(pProperty);
645
646 // Add the API Version
647 pProperty = new MgStringProperty(MgServerInformationProperties::ApiVersion, ApiVersion);
648 pProperties->Add(pProperty);
649
650 MG_CATCH_AND_THROW(L"MgServerManager.GetSiteStatus")
651
652 return pProperties.Detach();
653}
654
655MgByteReader* MgServerManager::GetDocument(CREFSTRING identifier)
656{
657 Ptr<MgByteReader> pByteReader;
658 pByteReader = NULL;
659
660 MG_TRY()
661
662 MG_LOG_TRACE_ENTRY(L"MgServerManager::GetDocument()");
663
664 // Need to seperate the identifier into the path tag and filename
665 STRING pathTag;
666 STRING fileTag;
667
668 bool bValid = ParseDocumentIdentifier(identifier, pathTag, fileTag);
669 if(bValid)
670 {
671 STRING filename = GetDocumentIdentifierFilename(pathTag, fileTag);
672 if(!filename.empty())
673 {
674 Ptr<MgByteSource> byteSource = new MgByteSource(filename);
675 pByteReader = byteSource->GetReader();
676 }
677 else
678 {
679 // Invalid document identifier
680 MgStringCollection arguments;
681 arguments.Add(L"1");
682 arguments.Add(identifier);
683
684 throw new MgException(MgExceptionCodes::MgInvalidArgumentException, L"MgServerManager.GetDocument",
685 __LINE__, __WFILE__, &arguments, L"MgDocumentIdentifierFilenameFailed", NULL);
686 }
687 }
688 else
689 {
690 // Invalid document identifier
691 MgStringCollection arguments;
692 arguments.Add(L"1");
693 arguments.Add(identifier);
694
695 MgStringCollection whyArguments;
696 whyArguments.Add(L"");
697
698 throw new MgException(MgExceptionCodes::MgInvalidArgumentException, L"MgServerManager.GetDocument",
699 __LINE__, __WFILE__, &arguments, L"MgStringContainsReservedCharacters", &whyArguments);
700 }
701
702 MG_CATCH_AND_THROW(L"MgServerManager.GetDocument")
703
704 return pByteReader.Detach();
705}
706void MgServerManager::SetDocument(CREFSTRING identifier, MgByteReader* data)
707{
708 MG_TRY()
709
710 MG_LOG_TRACE_ENTRY(L"MgServerManager::SetDocument()");
711
712 // Need to seperate the identifier into the path tag and filename
713 STRING pathTag;
714 STRING fileTag;
715
716 bool bValid = ParseDocumentIdentifier(identifier, pathTag, fileTag);
717 if(bValid)
718 {
719 STRING filename = GetDocumentIdentifierFilename(pathTag, fileTag);
720 if(!filename.empty())
721 {
722 // Create document directory if it does not exist
723 STRING path;
724
725 // Lookup path tag to determine actually path
726 STRING configurationPropertyName = pathTag + MgServerManager::DocumentPath;
727
728 MgConfiguration* pConfiguration = MgConfiguration::GetInstance();
729 pConfiguration->GetStringValue(MgConfigProperties::GeneralPropertiesSection, configurationPropertyName, path, L"");
730 if(!path.empty())
731 {
732 MgFileUtil::AppendSlashToEndOfPath(path);
733
734 // Create the directory if it doesn't exist
735 MgFileUtil::CreateDirectory(path, false);
736 }
737
738 MgByteSink byteSink(data);
739 byteSink.ToFile(filename);
740 }
741 else
742 {
743 // Invalid document identifier
744 MgStringCollection arguments;
745 arguments.Add(L"1");
746 arguments.Add(identifier);
747
748 throw new MgException(MgExceptionCodes::MgInvalidArgumentException, L"MgServerManager.SetDocument",
749 __LINE__, __WFILE__, &arguments, L"MgDocumentIdentifierFilenameFailed", NULL);
750 }
751 }
752 else
753 {
754 // Invalid document identifier
755 MgStringCollection arguments;
756 arguments.Add(L"1");
757 arguments.Add(identifier);
758
759 MgStringCollection whyArguments;
760 whyArguments.Add(L"");
761
762 throw new MgException(MgExceptionCodes::MgInvalidArgumentException, L"MgServerManager.SetDocument",
763 __LINE__, __WFILE__, &arguments, L"MgStringContainsReservedCharacters", &whyArguments);
764 }
765
766 MG_CATCH_AND_THROW(L"MgServerManager.SetDocument")
767}
768
769INT32 MgServerManager::GetAdminPort()
770{
771 return m_nAdminPort;
772}
773
774INT32 MgServerManager::GetAdminThreads()
775{
776 return m_nAdminThreads;
777}
778
779STRING MgServerManager::GetAdminEmail()
780{
781 return m_adminEmail;
782}
783
784INT32 MgServerManager::GetClientPort()
785{
786 return m_nClientPort;
787}
788
789INT32 MgServerManager::GetClientThreads()
790{
791 return m_nClientThreads;
792}
793
794INT32 MgServerManager::GetSitePort()
795{
796 return m_nSitePort;
797}
798
799INT32 MgServerManager::GetSiteThreads()
800{
801 return m_nSiteThreads;
802}
803
804void MgServerManager::TakeOffline()
805{
806 if (MgServerManager::ssOffline != m_ssServerStatus)
807 {
808 // Un-register the server services.
809 MgLoadBalanceManager::GetInstance()->UnregisterServices();
810
811 // Clear the server caches.
812 MgCacheManager::GetInstance()->ClearCaches();
813
814 m_ssServerStatus = MgServerManager::ssOffline;
815 }
816}
817
818void MgServerManager::BringOnline()
819{
820 if (MgServerManager::ssOnline != m_ssServerStatus)
821 {
822 MgLoadBalanceManager* loadBalanceManager = MgLoadBalanceManager::GetInstance();
823 ACE_ASSERT(NULL != loadBalanceManager);
824
825 if (NULL != loadBalanceManager && loadBalanceManager->RegisterServices())
826 {
827 m_ssServerStatus = MgServerManager::ssOnline;
828 }
829 }
830}
831
832bool MgServerManager::IsOnline()
833{
834 return MgServerManager::ssOnline == m_ssServerStatus ? true : false;
835}
836
837ACE_Time_Value MgServerManager::GetStartTime()
838{
839 return m_startTime;
840}
841
842INT32 MgServerManager::GetTotalReceivedOperations()
843{
844 return m_totalReceivedOperations.value();
845}
846
847INT32 MgServerManager::GetTotalProcessedOperations()
848{
849 return m_totalProcessedOperations.value();
850}
851
852INT64 MgServerManager::GetTotalOperationTime()
853{
854 return m_totalOperationTime.value();
855}
856
857void MgServerManager::IncrementOperationTime(INT64 operationTime)
858{
859 m_totalOperationTime += operationTime;
860}
861
862void MgServerManager::IncrementReceivedOperations()
863{
864 m_totalReceivedOperations++;
865}
866
867void MgServerManager::IncrementProcessedOperations()
868{
869 m_totalProcessedOperations++;
870}
871
872void MgServerManager::SetAdminMessageQueue(ACE_Message_Queue<ACE_MT_SYNCH>* pMessageQueue)
873{
874 m_pAdminMessageQueue = pMessageQueue;
875}
876
877void MgServerManager::SetClientMessageQueue(ACE_Message_Queue<ACE_MT_SYNCH>* pMessageQueue)
878{
879 m_pClientMessageQueue = pMessageQueue;
880}
881
882void MgServerManager::SetSiteMessageQueue(ACE_Message_Queue<ACE_MT_SYNCH>* pMessageQueue)
883{
884 m_pSiteMessageQueue = pMessageQueue;
885}
886
887ACE_Message_Queue<ACE_MT_SYNCH>* MgServerManager::GetAdminMessageQueue()
888{
889 return m_pAdminMessageQueue;
890}
891
892ACE_Message_Queue<ACE_MT_SYNCH>* MgServerManager::GetClientMessageQueue()
893{
894 return m_pClientMessageQueue;
895}
896
897ACE_Message_Queue<ACE_MT_SYNCH>* MgServerManager::GetSiteMessageQueue()
898{
899 return m_pSiteMessageQueue;
900}
901
902INT32 MgServerManager::GetAdminOperationsQueueCount()
903{
904 int nOperationQueueCount = -1;
905
906 if(m_pAdminMessageQueue)
907 {
908 nOperationQueueCount = m_pAdminMessageQueue->message_count();
909 }
910
911 return nOperationQueueCount;
912}
913
914INT32 MgServerManager::GetClientOperationsQueueCount()
915{
916 int nOperationQueueCount = -1;
917
918 if(m_pClientMessageQueue)
919 {
920 nOperationQueueCount = m_pClientMessageQueue->message_count();
921 }
922
923 return nOperationQueueCount;
924}
925
926INT32 MgServerManager::GetSiteOperationsQueueCount()
927{
928 int nOperationQueueCount = -1;
929
930 if(m_pSiteMessageQueue)
931 {
932 nOperationQueueCount = m_pSiteMessageQueue->message_count();
933 }
934
935 return nOperationQueueCount;
936}
937
938INT32 MgServerManager::GetTotalConnections()
939{
940 return m_totalConnections.value();
941}
942
943INT32 MgServerManager::GetTotalActiveConnections()
944{
945 return m_totalActiveConnections.value();
946}
947
948void MgServerManager::IncrementActiveConnections()
949{
950 m_totalActiveConnections++;
951
952 // Increment the total connections
953 m_totalConnections++;
954
955#ifdef _WIN32
956 // The ACE SELECT reactor does not have the same handle limit as the ACE WFMO reactor.
957 // The code below is left as is, but commented out in case the ACE WFMO reactor is ever used in the future.
958
959 // The limit for the default Windows ACE WFMO reactor is 62 handles this is due to the 64 handle limit of
960 // the Windows WaitForMultipleObjects() API, but ACE uses 2 handles internally leaving only 62 handles for the application.
961 // The only reason the value 55 is chosen is because it is slightly under this value and
962 // so we can log an error as the # of active connections approaches the current ACE reactor limit.
963/*
964 if(m_totalActiveConnections.value() > 55)
965 {
966 STRING strActiveConnections = L"";
967 MgUtil::Int32ToString(m_totalActiveConnections.value(), strActiveConnections);
968
969 STRING message = L"The active connection limit is about to be exceeded. Current active connections is ";
970 message += strActiveConnections;
971
972 // We are dangerously close to exceeding the safe # of active connections for the current ACE reactor
973 MG_LOG_ERROR_ENTRY(message.c_str());
974 }
975*/
976#else
977 // Linux uses a different ACE reactor and so this error message doesn't apply.
978#endif
979}
980
981void MgServerManager::DecrementActiveConnections()
982{
983 m_totalActiveConnections--;
984
985 // This should not go below 0
986 if(m_totalActiveConnections < 0)
987 {
988 m_totalActiveConnections = 0;
989 }
990}
991
992///////////////////////////////////////////////////////////////////////////////////
993/// <summary>
994/// Gets the total physical memory in bytes.
995/// </summary>
996/// <returns>
997/// The total physical memory in bytes.
998/// </returns>
999///
1000/// EXCEPTIONS:
1001/// MgConnectionNotOpenException
1002INT64 MgServerManager::GetTotalPhysicalMemory()
1003{
1004 INT64 nMemory = -1;
1005
1006 MG_TRY()
1007
1008 #ifdef _WIN32
1009 MEMORYSTATUSEX statex;
1010 statex.dwLength = sizeof(statex);
1011
1012 if (GlobalMemoryStatusEx(&statex))
1013 {
1014 nMemory = (INT64)statex.ullTotalPhys;
1015 }
1016
1017 #else
1018 MgLinuxMemoryStatus linuxMemoryStatus;
1019
1020 if (MgUtil::GetLinuxMemoryStatus(&linuxMemoryStatus))
1021 {
1022 nMemory = linuxMemoryStatus.m_memTotal;
1023 }
1024
1025 #endif // _WIN32
1026
1027
1028 MG_CATCH_AND_THROW(L"MgServerManager.GetTotalPhysicalMemory")
1029
1030 return nMemory;
1031
1032}
1033
1034///////////////////////////////////////////////////////////////////////////////////
1035/// <summary>
1036/// Gets the available physical memory in bytes.
1037/// </summary>
1038/// <returns>
1039/// The available physical memory in bytes.
1040/// </returns>
1041///
1042/// EXCEPTIONS:
1043/// MgConnectionNotOpenException
1044INT64 MgServerManager::GetAvailablePhysicalMemory()
1045{
1046 INT64 nMemory = -1;
1047
1048 MG_TRY()
1049
1050 #ifdef _WIN32
1051 MEMORYSTATUSEX statex;
1052 statex.dwLength = sizeof(statex);
1053
1054 if (GlobalMemoryStatusEx(&statex))
1055 {
1056 nMemory = (INT64)statex.ullAvailPhys;
1057 }
1058
1059 #else
1060 MgLinuxMemoryStatus linuxMemoryStatus;
1061
1062 if (MgUtil::GetLinuxMemoryStatus(&linuxMemoryStatus))
1063 {
1064 nMemory = linuxMemoryStatus.m_memFree;
1065 }
1066
1067 #endif // _WIN32
1068
1069
1070 MG_CATCH_AND_THROW(L"MgServerManager.GetAvailablePhysicalMemory")
1071
1072 return nMemory;
1073}
1074
1075///////////////////////////////////////////////////////////////////////////////////
1076/// <summary>
1077/// Gets the total virtual memory in bytes.
1078/// </summary>
1079/// <returns>
1080/// The total virtual memory in bytes.
1081/// </returns>
1082///
1083/// EXCEPTIONS:
1084/// MgConnectionNotOpenException
1085INT64 MgServerManager::GetTotalVirtualMemory()
1086{
1087 INT64 nMemory = -1;
1088
1089 MG_TRY()
1090
1091 #ifdef _WIN32
1092 MEMORYSTATUSEX statex;
1093 statex.dwLength = sizeof(statex);
1094
1095 if (GlobalMemoryStatusEx(&statex))
1096 {
1097 nMemory = (INT64)statex.ullTotalVirtual;
1098 }
1099
1100 #else
1101 MgLinuxMemoryStatus linuxMemoryStatus;
1102
1103 if (MgUtil::GetLinuxMemoryStatus(&linuxMemoryStatus))
1104 {
1105 nMemory = linuxMemoryStatus.m_swapTotal;
1106 }
1107
1108
1109 #endif // _WIN32
1110
1111
1112 MG_CATCH_AND_THROW(L"MgServerManager.GetTotalVirtualMemory");
1113
1114 return nMemory;
1115}
1116
1117///////////////////////////////////////////////////////////////////////////////////
1118/// <summary>
1119/// Gets the available virtual memory in bytes.
1120/// </summary>
1121/// <returns>
1122/// The available virtual memory in bytes.
1123/// </returns>
1124///
1125/// EXCEPTIONS:
1126/// MgConnectionNotOpenException
1127INT64 MgServerManager::GetAvailableVirtualMemory()
1128{
1129 INT64 nMemory = -1;
1130
1131 MG_TRY()
1132
1133 #ifdef _WIN32
1134 MEMORYSTATUSEX statex;
1135 statex.dwLength = sizeof(statex);
1136
1137 if (GlobalMemoryStatusEx(&statex))
1138 {
1139 nMemory = (INT64)statex.ullAvailVirtual;
1140 }
1141
1142 #else
1143 MgLinuxMemoryStatus linuxMemoryStatus;
1144
1145 if (MgUtil::GetLinuxMemoryStatus(&linuxMemoryStatus))
1146 {
1147 nMemory = linuxMemoryStatus.m_swapFree;
1148 }
1149
1150 #endif
1151
1152
1153 MG_CATCH_AND_THROW(L"MgServerManager.GetAvailableVirtualMemory");
1154
1155 return nMemory;
1156}
1157
1158///////////////////////////////////////////////////////////////////////////////////
1159/// <summary>
1160/// Gets the amount of time that the server has been up and running.
1161/// </summary>
1162/// <returns>
1163/// The server up time in seconds.
1164/// </returns>
1165///
1166/// EXCEPTIONS:
1167/// MgConnectionNotOpenException
1168INT64 MgServerManager::GetUptime()
1169{
1170 ACE_Time_Value upTime(0);
1171
1172 MG_TRY()
1173
1174 upTime = ACE_OS::gettimeofday() - GetStartTime();
1175
1176 MG_CATCH_AND_THROW(L"MgServerManager.GetUptime");
1177
1178 return (INT64)upTime.sec();
1179}
1180
1181///////////////////////////////////////////////////////////////////////////////////
1182/// <summary>
1183/// Gets the average time to process an operation.
1184/// </summary>
1185/// <returns>
1186/// The average time to process an operation in milliseconds.
1187/// </returns>
1188///
1189/// EXCEPTIONS:
1190/// MgConnectionNotOpenException
1191INT64 MgServerManager::GetAverageOperationTime()
1192{
1193 double avgTime = 0.0;
1194
1195 MG_TRY()
1196
1197 if (GetTotalProcessedOperations() > 0)
1198 {
1199 avgTime = ((double)(GetTotalOperationTime())) / (double)(GetTotalProcessedOperations());
1200 }
1201
1202
1203 MG_CATCH_AND_THROW(L"MgServerManager.GetAverageOperationTime")
1204
1205 return (INT64)avgTime;
1206}
1207
1208///////////////////////////////////////////////////////////////////////////////////
1209/// <summary>
1210/// Helper method to compute the current CPU load on WIN32.
1211/// </summary>
1212/// <returns>
1213/// The total the current CPU load in percent.
1214/// </returns>
1215///
1216/// EXCEPTIONS:
1217/// MgConnectionNotOpenException
1218INT32 MgServerManager::ComputeWIN32CpuLoad()
1219{
1220 INT32 nCpuLoad = -1;
1221
1222 #ifdef _WIN32
1223
1224 HQUERY hQuery;
1225 HGLOBAL hAlloc;
1226 HCOUNTER *pCounterHandle;
1227 PDH_STATUS pdhStatus;
1228 PDH_FMT_COUNTERVALUE fmtValue;
1229 DWORD ctrType;
1230 wchar_t szPathBuffer[MAX_PATH];
1231
1232 // Open the query object.
1233 pdhStatus = PdhOpenQuery (0, 0, &hQuery);
1234
1235 // Allocate the counter handle array.
1236 hAlloc = ::GlobalAlloc(GPTR, sizeof(HCOUNTER));
1237
1238 wcscpy(szPathBuffer, L"\\Process(Idle)\\% Processor Time"); // NOXLATE
1239
1240 pCounterHandle = (HCOUNTER*)hAlloc;
1241 pdhStatus = PdhAddCounter (hQuery,
1242 szPathBuffer,
1243 0,
1244 pCounterHandle);
1245
1246 // Prime the counter for computing the CPU load over the sample interval.
1247 pdhStatus = PdhCollectQueryData (hQuery);
1248
1249 // Wait one interval.
1250 ACE_OS::sleep(1);
1251
1252 // Get the current data values.
1253 pdhStatus = PdhCollectQueryData (hQuery);
1254
1255 // Get the current value of this counter.
1256 pdhStatus = PdhGetFormattedCounterValue (*pCounterHandle,
1257 PDH_FMT_LONG,
1258 &ctrType,
1259 &fmtValue);
1260
1261 if (pdhStatus == ERROR_SUCCESS)
1262 {
1263 nCpuLoad = 100 - (INT32)fmtValue.longValue;
1264 }
1265
1266 // Close the query.
1267 pdhStatus = PdhCloseQuery (hQuery);
1268
1269 // Free memory
1270 ::GlobalFree(hAlloc);
1271
1272 #else
1273
1274 throw new MgException(MgExceptionCodes::MgPlatformNotSupportedException, L"MgServerManager.ComputeWIN32CpuLoad", __LINE__, __WFILE__, NULL, L"", NULL);
1275
1276 #endif // _WIN32
1277
1278 return nCpuLoad;
1279}
1280
1281///////////////////////////////////////////////////////////////////////////////////
1282/// <summary>
1283/// Helper method to compute the current CPU load on Linux.
1284/// </summary>
1285/// <returns>
1286/// The total the current CPU load in percent.
1287/// </returns>
1288INT32 MgServerManager::ComputeLinuxCpuLoad()
1289{
1290 INT32 nCpuLoad = -1;
1291
1292 #ifdef _WIN32
1293
1294 throw new MgException(MgExceptionCodes::MgPlatformNotSupportedException, L"MgServerManager.ComputeLinuxCpuLoad", __LINE__, __WFILE__, NULL, L"", NULL);
1295
1296 #else
1297
1298 FILE* stat;
1299 char line[80];
1300 int user;
1301 int nice;
1302 int sys;
1303 int idle;
1304 int ouser;
1305 int onice;
1306 int osys;
1307 int oidle;
1308 double load;
1309
1310 // Prime initial values for computing the CPU load over the sample interval
1311 stat = fopen( ( MgUtil::WideCharToMultiByte(MgUtil::LinuxFilesystemStat) ).c_str(), "r" );
1312 if (NULL == stat)
1313 {
1314 MgStringCollection arguments;
1315 arguments.Add(MgUtil::LinuxFilesystemStat);
1316 throw new MgException(MgExceptionCodes::MgFileNotFoundException, L"MgServerManager.ComputeLinuxCpuLoad", __LINE__, __WFILE__, &arguments, L"", NULL);
1317 }
1318 fgets(line, 80, stat);
1319 sscanf(line, "%*3s %i %i %i %i", &ouser, &onice, &osys, &oidle);
1320 fclose(stat);
1321
1322 // Wait one interval.
1323 ACE_OS::sleep(1);
1324
1325 // Get the current data values
1326 stat = fopen( ( MgUtil::WideCharToMultiByte(MgUtil::LinuxFilesystemStat) ).c_str(), "r");
1327 if(NULL == stat)
1328 {
1329 MgStringCollection arguments;
1330 arguments.Add(MgUtil::LinuxFilesystemStat);
1331 throw new MgException(MgExceptionCodes::MgFileNotFoundException, L"MgServerManager.ComputeLinuxCpuLoad", __LINE__, __WFILE__, &arguments, L"", NULL);
1332 }
1333 fgets(line, 80, stat);
1334 sscanf(line, "%*3s %i %i %i %i", &user, &nice, &sys, &idle);
1335 fclose(stat);
1336
1337 load = (double)(idle-oidle) / (double)( (user-ouser) + (nice-onice) + (sys-osys) + (idle-oidle) ) * 100;
1338
1339 nCpuLoad = 100 - (INT32)load;
1340
1341 #endif // _WIN32
1342
1343 return nCpuLoad;
1344}
1345
1346#ifdef _WIN32
1347// Note: This code is a modified version taken from the Microsoft SDK
1348STRING MgServerManager::GetOperatingSystemVersion()
1349{
1350 STRING osVersion;
1351 OSVERSIONINFOEX osvi;
1352 bool bOsVersionInfoEx = false;
1353 bool bHaveVersion = false;
1354
1355 // Set to default
1356 osVersion = L"Microsoft Windows";
1357
1358 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
1359 // If that fails, try using the OSVERSIONINFO structure.
1360
1361 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
1362 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
1363
1364 if((bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi)))
1365 {
1366 bHaveVersion = true;
1367 }
1368 else
1369 {
1370 // Try using standard version infor structure
1371 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1372 if (GetVersionEx((OSVERSIONINFO *)&osvi))
1373 {
1374 bHaveVersion = true;
1375 }
1376 }
1377
1378 if(bHaveVersion)
1379 {
1380 switch (osvi.dwPlatformId)
1381 {
1382 // Test for the Windows NT product family.
1383 case VER_PLATFORM_WIN32_NT:
1384
1385 // Test for the specific product family.
1386 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
1387 osVersion = L"Microsoft Windows Server 2003 family, ";
1388
1389 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
1390 osVersion = L"Microsoft Windows XP ";
1391
1392 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
1393 osVersion = L"Microsoft Windows 2000 ";
1394
1395 if ( osvi.dwMajorVersion <= 4 )
1396 osVersion = L"Microsoft Windows NT ";
1397
1398 // Test for specific product on Windows NT 4.0 SP6 and later.
1399 if( bOsVersionInfoEx )
1400 {
1401 // Test for the workstation type.
1402 if ( osvi.wProductType == VER_NT_WORKSTATION )
1403 {
1404 if( osvi.dwMajorVersion == 4 )
1405 osVersion += L"Workstation 4.0 ";
1406 else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
1407 osVersion += L"Home Edition ";
1408 else
1409 osVersion += L"Professional ";
1410 }
1411
1412 // Test for the server type.
1413 else if ( osvi.wProductType == VER_NT_SERVER )
1414 {
1415 if( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
1416 {
1417 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
1418 osVersion += L"Datacenter Edition ";
1419 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
1420 osVersion += L"Enterprise Edition ";
1421 else if ( osvi.wSuiteMask == VER_SUITE_BLADE )
1422 osVersion += L"Web Edition ";
1423 else
1424 osVersion += L"Standard Edition ";
1425 }
1426 else if( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
1427 {
1428 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
1429 osVersion += L"Datacenter Server ";
1430 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
1431 osVersion += L"Advanced Server ";
1432 else
1433 osVersion += L"Server ";
1434 }
1435 else // Windows NT 4.0
1436 {
1437 if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
1438 osVersion += L"Server 4.0, Enterprise Edition ";
1439 else
1440 osVersion += L"Server 4.0 ";
1441 }
1442 }
1443 }
1444 else // Test for specific product on Windows NT 4.0 SP5 and earlier
1445 {
1446 HKEY hKey;
1447 wchar_t wszProductType[255];
1448 DWORD dwBufLen = 255;
1449 LONG lRet;
1450
1451 lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey );
1452 if( lRet == ERROR_SUCCESS )
1453 {
1454 lRet = RegQueryValueEx( hKey, L"ProductType", NULL, NULL, (LPBYTE) wszProductType, &dwBufLen);
1455 if( (lRet == ERROR_SUCCESS) && (dwBufLen < 255) )
1456 {
1457 if ( ACE_OS::strcmp(L"WINNT", wszProductType) == 0 )
1458 osVersion += L"Workstation ";
1459 if ( ACE_OS::strcmp(L"LANMANNT", wszProductType) == 0 )
1460 osVersion += L"Server ";
1461 if ( ACE_OS::strcmp(L"SERVERNT", wszProductType) == 0 )
1462 osVersion += L"Advanced Server ";
1463 }
1464
1465 RegCloseKey( hKey );
1466 }
1467 }
1468
1469 // Display service pack (if any) and build number.
1470 wchar_t wszTemp[255];
1471
1472 if( osvi.dwMajorVersion == 4 && ACE_OS::strcmp( osvi.szCSDVersion, L"Service Pack 6" ) == 0 )
1473 {
1474 HKEY hKey;
1475 LONG lRet;
1476
1477 // Test for SP6 versus SP6a.
1478 lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009", 0, KEY_QUERY_VALUE, &hKey );
1479 if( lRet == ERROR_SUCCESS )
1480 {
1481 swprintf(wszTemp, L"Service Pack 6a (Build %d)", osvi.dwBuildNumber & 0xFFFF);
1482 osVersion += wszTemp;
1483 }
1484 else // Windows NT 4.0 prior to SP6a
1485 {
1486 swprintf(wszTemp, L"%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
1487 osVersion += wszTemp;
1488 }
1489
1490 RegCloseKey( hKey );
1491 }
1492 else // Windows NT 3.51 and earlier or Windows 2000 and later
1493 {
1494 swprintf(wszTemp, L"%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
1495 osVersion += wszTemp;
1496 }
1497
1498 break;
1499
1500 // Test for the Windows 95 product family.
1501 case VER_PLATFORM_WIN32_WINDOWS:
1502
1503 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
1504 {
1505 osVersion = L"Microsoft Windows 95 ";
1506 if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
1507 osVersion += L"OSR2 ";
1508 }
1509
1510 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
1511 {
1512 osVersion = L"Microsoft Windows 98 ";
1513 if ( osvi.szCSDVersion[1] == 'A' )
1514 osVersion += L"SE ";
1515 }
1516
1517 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
1518 {
1519 osVersion = L"Microsoft Windows Millennium Edition";
1520 }
1521 break;
1522
1523 case VER_PLATFORM_WIN32s:
1524
1525 osVersion = L"Microsoft Win32s";
1526 break;
1527 }
1528 }
1529
1530 return osVersion;
1531}
1532#else
1533#include <sys/utsname.h>
1534// Linux Operating System Version
1535STRING MgServerManager::GetOperatingSystemVersion()
1536{
1537 STRING osVersion;
1538
1539 //SetDefault
1540 osVersion=L"Linux";
1541 char temp[100];
1542 struct utsname osInfo;
1543
1544 if (-1 !=uname(&osInfo))
1545 {
1546 snprintf(temp, 99, "%s, Kernel Version: %s", osInfo.sysname, osInfo.release);
1547 osVersion = MgUtil::MultiByteToWideChar(std::string(temp));
1548 }
1549
1550 return osVersion;
1551}
1552#endif
1553
1554void MgServerManager::AddClientHandle(ACE_HANDLE handle)
1555{
1556 if (m_pClientHandles)
1557 {
1558 // Mutex is shared with MgIdleTimeoutHandler::handle_timeout
1559 ACE_MT (ACE_GUARD_ACTION(ACE_Lock, ace_mon, ACE_Reactor::instance()->lock(), m_pClientHandles->insert(handle);, ;));
1560 }
1561}
1562
1563void MgServerManager::RemoveClientHandle(ACE_HANDLE handle)
1564{
1565 if (m_pClientHandles)
1566 {
1567 // Mutex is shared with MgIdleTimeoutHandler::handle_timeout
1568 ACE_MT (ACE_GUARD_ACTION(ACE_Lock, ace_mon, ACE_Reactor::instance()->lock(), m_pClientHandles->remove(handle);, ;));
1569 }
1570}
1571
1572bool MgServerManager::ParseDocumentIdentifier(CREFSTRING identifier, STRING& pathTag, STRING& fileTag)
1573{
1574 bool bResult = false;
1575
1576 // Initialize
1577 pathTag = L"";
1578 fileTag = L"";
1579
1580 size_t pos = identifier.find(L":");
1581 if(string::npos != pos)
1582 {
1583 // Is this a valid path tag?
1584 if(pos > 0)
1585 {
1586 // Valid path tag
1587 pathTag.assign(identifier, 0, pos);
1588
1589 // Is this a valid file tag?
1590 // Valid characters are: A-Za-Z0-9_.-+[]
1591 fileTag.assign(identifier, pos+1, identifier.length());
1592 if((string::npos == fileTag.find_first_not_of(L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.-+[]")) &&
1593 (string::npos == fileTag.find(L"..")))
1594 {
1595 // Valid file tag
1596 // Therefore, identifier is valid
1597 bResult = true;
1598 }
1599 }
1600 }
1601
1602 return bResult;
1603}
1604
1605STRING MgServerManager::GetDocumentIdentifierFilename(CREFSTRING pathTag, CREFSTRING fileTag)
1606{
1607 STRING filename;
1608 filename = L"";
1609
1610 // We have a valid identifier
1611 STRING path;
1612
1613 // Lookup path tag to determine actually path
1614 STRING configurationPropertyName = pathTag + MgServerManager::DocumentPath;
1615
1616 MgConfiguration* pConfiguration = MgConfiguration::GetInstance();
1617 pConfiguration->GetStringValue(MgConfigProperties::GeneralPropertiesSection, configurationPropertyName, path, L"");
1618 if(!path.empty())
1619 {
1620 MgFileUtil::AppendSlashToEndOfPath(path);
1621
1622 // Append the path to the filename
1623 filename = path + fileTag;
1624
1625 // Add extension
1626 filename += MgServerManager::DocumentExtension;
1627 }
1628
1629 return filename;
1630}
1631
1632void MgServerManager::StartWorkerThread(void (*function)())
1633{
1634 // We want the worker thread pool to do some work for us
1635 MgWorkerThreadData* wtd;
1636 ACE_NEW_NORETURN( wtd, MgWorkerThreadData( function ) );
1637
1638 ACE_Message_Block* mb;
1639 ACE_NEW_NORETURN( mb, ACE_Message_Block( wtd ) );
1640 if(mb)
1641 {
1642 mb->msg_type(ACE_Message_Block::MB_DATA);
1643 int nResult = m_pWorkerThreads->putq(mb);
1644 if(nResult == -1)
1645 {
1646 // Failed to queue the message
1647 STRING messageId;
1648 MgStringCollection arguments;
1649
1650 arguments.Add(L"Failed to queue ACE_Message_Block.");
1651 messageId = L"MgFormatInnerExceptionMessage";
1652
1653 MgException* mgException = new MgException(MgExceptionCodes::MgRuntimeException, L"MgServerManager.StartWorkerThread", __LINE__, __WFILE__, NULL, messageId, &arguments);
1654 throw mgException;
1655 }
1656 }
1657}
1658
1659void MgServerManager::StopWorkerThreads()
1660{
1661 // Tell the worker threads to stop
1662 ACE_Message_Block* mb = new ACE_Message_Block(4);
1663 if(mb)
1664 {
1665 mb->msg_type(ACE_Message_Block::MB_STOP);
1666 if (m_pWorkerThreads)
1667 {
1668 m_pWorkerThreads->putq(mb);
1669 }
1670 }
1671
1672 // Wait for threads to process STOP
1673 if (m_pWorkerThreads)
1674 {
1675 m_pWorkerThreads->wait();
1676 }
1677
1678 m_threadManager.wait(0,1);
1679 m_threadManager.close();
1680}
Note: See TracBrowser for help on using the repository browser.