Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

436 lines
12 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. PurgeEngine.cpp
  5. Abstract:
  6. This file contains the implementation of the MPCPurgeEngine class,
  7. that controls the cleaning of the temporary directories.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 07/12/99
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. HRESULT MPCPurgeEngine::Process()
  14. {
  15. __ULT_FUNC_ENTRY("MPCPurgeEngine::Process");
  16. HRESULT hr;
  17. HRESULT hr2;
  18. CISAPIconfig::Iter itInstanceBegin;
  19. CISAPIconfig::Iter itInstanceEnd;
  20. CISAPIinstance::PathIter itPathBegin;
  21. CISAPIinstance::PathIter itPathEnd;
  22. double dblNow = MPC::GetSystemTime();
  23. //
  24. // Enumerate all the instances.
  25. //
  26. __MPC_EXIT_IF_METHOD_FAILS(hr, g_Config.GetInstances( itInstanceBegin, itInstanceEnd ));
  27. for(;itInstanceBegin != itInstanceEnd; itInstanceBegin++)
  28. {
  29. __MPC_EXIT_IF_METHOD_FAILS(hr, itInstanceBegin->get_URL ( m_szURL ));
  30. __MPC_EXIT_IF_METHOD_FAILS(hr, itInstanceBegin->get_QueueSizeMax ( m_dwQueueSizeMax ));
  31. __MPC_EXIT_IF_METHOD_FAILS(hr, itInstanceBegin->get_QueueSizeThreshold( m_dwQueueSizeThreshold ));
  32. __MPC_EXIT_IF_METHOD_FAILS(hr, itInstanceBegin->get_MaximumJobAge ( m_dwMaximumJobAge ));
  33. m_dblMaximumJobAge = dblNow - m_dwMaximumJobAge;
  34. MPCServer mpcsServer( NULL, m_szURL.c_str(), NULL );
  35. m_mpcsServer = &mpcsServer;
  36. //
  37. // For each instance, enumerate all the temporary directories.
  38. //
  39. __MPC_EXIT_IF_METHOD_FAILS(hr, itInstanceBegin->GetLocations( itPathBegin, itPathEnd ));
  40. for(;itPathBegin != itPathEnd; itPathBegin++)
  41. {
  42. MPC::FileSystemObject fso( itPathBegin->c_str() );
  43. if(SUCCEEDED(hr2 = fso.Scan( true )))
  44. {
  45. DWORD dwTotalSize = 0;
  46. m_lstClients.clear();
  47. __MPC_EXIT_IF_METHOD_FAILS(hr, AnalyzeFolders( &fso, dwTotalSize ));
  48. __MPC_EXIT_IF_METHOD_FAILS(hr, RemoveOldJobs( dwTotalSize ));
  49. if(dwTotalSize > m_dwQueueSizeMax)
  50. {
  51. while(dwTotalSize && dwTotalSize > m_dwQueueSizeThreshold)
  52. {
  53. __MPC_EXIT_IF_METHOD_FAILS(hr, RemoveOldestJob ( dwTotalSize ));
  54. __MPC_EXIT_IF_METHOD_FAILS(hr, RemoveEmptyClients( dwTotalSize ));
  55. }
  56. }
  57. }
  58. }
  59. }
  60. hr = S_OK;
  61. __ULT_FUNC_CLEANUP;
  62. __ULT_FUNC_EXIT(hr);
  63. }
  64. /////////////////////////////////////////////////////////////////////////////
  65. /////////////////////////////////////////////////////////////////////////////
  66. static bool MatchExtension( const MPC::wstring& szPath ,
  67. LPCWSTR szExt )
  68. {
  69. MPC::wstring::size_type iPos;
  70. iPos = szPath.find( szExt, 0 );
  71. if(iPos != MPC::wstring::npos && iPos + wcslen( szExt ) == szPath.length())
  72. {
  73. return true;
  74. }
  75. return false;
  76. }
  77. HRESULT MPCPurgeEngine::AnalyzeFolders( /*[in]*/ MPC::FileSystemObject* fso ,
  78. /*[in]*/ DWORD& dwTotalSize )
  79. {
  80. __ULT_FUNC_ENTRY("MPCPurgeEngine::AnalyzeFolders");
  81. HRESULT hr;
  82. HRESULT hr2;
  83. MPC::FileSystemObject::List lst;
  84. MPC::FileSystemObject::Iter it;
  85. //
  86. // Process all folders.
  87. //
  88. __MPC_EXIT_IF_METHOD_FAILS(hr, fso->EnumerateFolders( lst ));
  89. for(it = lst.begin(); it != lst.end(); it++)
  90. {
  91. __MPC_EXIT_IF_METHOD_FAILS(hr, AnalyzeFolders( *it, dwTotalSize ));
  92. }
  93. //
  94. // Process all files.
  95. //
  96. __MPC_EXIT_IF_METHOD_FAILS(hr, fso->EnumerateFiles( lst ));
  97. for(it = lst.begin(); it != lst.end(); it++)
  98. {
  99. MPC::wstring szPath;
  100. __MPC_EXIT_IF_METHOD_FAILS(hr, (*it)->get_Path( szPath ));
  101. if(MatchExtension( szPath, CLIENT_CONST__DB_EXTENSION ))
  102. {
  103. __MPC_EXIT_IF_METHOD_FAILS(hr, AddClient( szPath, dwTotalSize ));
  104. }
  105. else if(MatchExtension( szPath, SESSION_CONST__IMG_EXTENSION ))
  106. {
  107. ;
  108. }
  109. else
  110. {
  111. //
  112. // Any other file should be deleted.
  113. //
  114. (void)(*it)->Delete();
  115. }
  116. }
  117. hr = S_OK;
  118. __ULT_FUNC_CLEANUP;
  119. __ULT_FUNC_EXIT(hr);
  120. }
  121. /////////////////////////////////////////////////////////////////////////////
  122. HRESULT MPCPurgeEngine::AddClient( /*[in]*/ const MPC::wstring& szPath ,
  123. /*[in/out]*/ DWORD& dwTotalSize )
  124. {
  125. __ULT_FUNC_ENTRY("MPCPurgeEngine::AddClient");
  126. HRESULT hr;
  127. HRESULT hr2;
  128. MPCClient mpccClient( m_mpcsServer, szPath );
  129. Iter itClient = m_lstClients.insert( m_lstClients.end(), MPCPurge_ClientSummary( szPath ) );
  130. if(SUCCEEDED(hr2 = mpccClient.InitFromDisk( false )))
  131. {
  132. MPCClient::Iter itBegin;
  133. MPCClient::Iter itEnd;
  134. //
  135. // Adjust total count with size of the Directory File.
  136. //
  137. __MPC_EXIT_IF_METHOD_FAILS(hr, mpccClient.GetFileSize( itClient->m_dwFileSize ));
  138. dwTotalSize += itClient->m_dwFileSize;
  139. __MPC_EXIT_IF_METHOD_FAILS(hr, mpccClient.GetSessions( itBegin, itEnd ));
  140. while(itBegin != itEnd)
  141. {
  142. MPCPurge_SessionSummary pssSession;
  143. itBegin->get_JobID ( pssSession.m_szJobID );
  144. itBegin->get_LastModified( pssSession.m_dblLastModified );
  145. itBegin->get_CurrentSize ( pssSession.m_dwCurrentSize );
  146. //
  147. // Don't count "committed" jobs in total size, because the file has already been moved.
  148. //
  149. if(itBegin->get_Committed())
  150. {
  151. pssSession.m_dwCurrentSize = 0;
  152. }
  153. itClient->m_lstSessions.push_back( pssSession );
  154. dwTotalSize += pssSession.m_dwCurrentSize;
  155. itBegin++;
  156. }
  157. }
  158. hr = S_OK;
  159. __ULT_FUNC_CLEANUP;
  160. __ULT_FUNC_EXIT(hr);
  161. }
  162. /////////////////////////////////////////////////////////////////////////////
  163. HRESULT MPCPurgeEngine::RemoveOldJobs( /*[in/out]*/ DWORD& dwTotalSize )
  164. {
  165. __ULT_FUNC_ENTRY("MPCPurgeEngine::RemoveOldJobs");
  166. HRESULT hr;
  167. HRESULT hr2;
  168. Iter it;
  169. for(it = m_lstClients.begin(); it != m_lstClients.end(); it++)
  170. {
  171. MPCPurge_ClientSummary::Iter itSession;
  172. MPCClient mpccClient( m_mpcsServer, it->m_szPath );
  173. bool fInitialized = false;
  174. while(it->GetOldestSession( itSession ))
  175. {
  176. //
  177. // If the oldest session is younger than the limit, leave the loop.
  178. //
  179. if(itSession->m_dblLastModified > m_dblMaximumJobAge)
  180. {
  181. break;
  182. }
  183. __MPC_EXIT_IF_METHOD_FAILS(hr, RemoveSession( mpccClient, fInitialized, it, itSession, dwTotalSize ));
  184. }
  185. }
  186. hr = S_OK;
  187. __ULT_FUNC_CLEANUP;
  188. __ULT_FUNC_EXIT(hr);
  189. }
  190. /////////////////////////////////////////////////////////////////////////////
  191. HRESULT MPCPurgeEngine::RemoveOldestJob( /*[in/out]*/ DWORD& dwTotalSize )
  192. {
  193. __ULT_FUNC_ENTRY("MPCPurgeEngine::RemoveOldestJob");
  194. HRESULT hr;
  195. HRESULT hr2;
  196. Iter it;
  197. Iter itOldestClient;
  198. double dblOldestClient = DBL_MAX;
  199. bool fFound = false;
  200. //
  201. // Look for the oldest job.
  202. //
  203. for(it = m_lstClients.begin(); it != m_lstClients.end(); it++)
  204. {
  205. if(it->m_dblLastModified < dblOldestClient)
  206. {
  207. itOldestClient = it;
  208. dblOldestClient = it->m_dblLastModified;
  209. fFound = true;
  210. }
  211. }
  212. if(fFound)
  213. {
  214. MPCPurge_ClientSummary::Iter itSession;
  215. MPCClient mpccClient( m_mpcsServer, itOldestClient->m_szPath );
  216. bool fInitialized = false;
  217. if(itOldestClient->GetOldestSession( itSession ))
  218. {
  219. __MPC_EXIT_IF_METHOD_FAILS(hr, RemoveSession( mpccClient, fInitialized, itOldestClient, itSession, dwTotalSize ));
  220. //
  221. // Update the m_dblLastModified of the MPCPurge_ClientSummary object.
  222. //
  223. itOldestClient->GetOldestSession( itSession );
  224. }
  225. if(fInitialized)
  226. {
  227. DWORD dwPost;
  228. __MPC_EXIT_IF_METHOD_FAILS(hr, mpccClient.SyncToDisk ( ));
  229. __MPC_EXIT_IF_METHOD_FAILS(hr, mpccClient.GetFileSize( dwPost ));
  230. //
  231. // Update Directory File size.
  232. //
  233. dwTotalSize -= itOldestClient->m_dwFileSize;
  234. dwTotalSize += dwPost;
  235. itOldestClient->m_dwFileSize = dwPost;
  236. }
  237. }
  238. hr = S_OK;
  239. __ULT_FUNC_CLEANUP;
  240. __ULT_FUNC_EXIT(hr);
  241. }
  242. /////////////////////////////////////////////////////////////////////////////
  243. HRESULT MPCPurgeEngine::RemoveSession( /*[in]*/ MPCClient& mpccClient ,
  244. /*[in/out]*/ bool& fInitialized ,
  245. /*[in]*/ Iter itClient ,
  246. /*[in]*/ MPCPurge_ClientSummary::Iter& itSession ,
  247. /*[in/out]*/ DWORD& dwTotalSize )
  248. {
  249. __ULT_FUNC_ENTRY("MPCPurgeEngine::RemoveSession");
  250. HRESULT hr;
  251. HRESULT hr2;
  252. //
  253. // Lock the client.
  254. //
  255. if(fInitialized == false)
  256. {
  257. if(SUCCEEDED(hr2 = mpccClient.InitFromDisk( false )))
  258. {
  259. fInitialized = true;
  260. }
  261. }
  262. if(fInitialized)
  263. {
  264. MPCClient::Iter itSessionReal;
  265. //
  266. // If the session exists, remove it.
  267. //
  268. if(mpccClient.Find( itSession->m_szJobID, itSessionReal ) == true)
  269. {
  270. __MPC_EXIT_IF_METHOD_FAILS(hr, itSessionReal->RemoveFile());
  271. mpccClient.Erase( itSessionReal );
  272. }
  273. //
  274. // Update the total size counter and remove the session from memory.
  275. //
  276. dwTotalSize -= itSession->m_dwCurrentSize;
  277. itClient->m_lstSessions.erase( itSession );
  278. }
  279. hr = S_OK;
  280. __ULT_FUNC_CLEANUP;
  281. __ULT_FUNC_EXIT(hr);
  282. }
  283. /////////////////////////////////////////////////////////////////////////////
  284. HRESULT MPCPurgeEngine::RemoveEmptyClients( /*[in/out]*/ DWORD& dwTotalSize )
  285. {
  286. __ULT_FUNC_ENTRY("MPCPurgeEngine::RemoveEmptyClients");
  287. HRESULT hr;
  288. Iter it;
  289. for(it = m_lstClients.begin(); it != m_lstClients.end(); it++)
  290. {
  291. //
  292. // If the client has no more sessions, don't count it.
  293. //
  294. if(it->m_lstSessions.size() == 0)
  295. {
  296. dwTotalSize -= it->m_dwFileSize;
  297. m_lstClients.erase( it ); it = m_lstClients.begin();
  298. }
  299. }
  300. hr = S_OK;
  301. // __ULT_FUNC_CLEANUP;
  302. __ULT_FUNC_EXIT(hr);
  303. }
  304. /////////////////////////////////////////////////////////////////////////////
  305. /////////////////////////////////////////////////////////////////////////////
  306. /////////////////////////////////////////////////////////////////////////////
  307. MPCPurge_ClientSummary::MPCPurge_ClientSummary( const MPC::wstring& szPath )
  308. {
  309. m_szPath = szPath; // MPC::wstring m_szPath;
  310. // List m_lstSessions;
  311. m_dwFileSize = 0; // DWORD m_dwFileSize;
  312. m_dblLastModified = 0; // double m_dblLastModified;
  313. }
  314. bool MPCPurge_ClientSummary::GetOldestSession( /*[out]*/ Iter& itSession )
  315. {
  316. Iter it;
  317. m_dblLastModified = DBL_MAX;
  318. itSession = m_lstSessions.end();
  319. for(it = m_lstSessions.begin(); it != m_lstSessions.end(); it++)
  320. {
  321. if(it->m_dblLastModified < m_dblLastModified)
  322. {
  323. itSession = it;
  324. m_dblLastModified = it->m_dblLastModified;
  325. }
  326. }
  327. return (itSession != m_lstSessions.end());
  328. }