/CCGOnline/CCGOnline/IPDatabase/DatabaseProcessBase.cpp

https://github.com/bretambrose/CCGOnlinePublic · C++ · 197 lines · 139 code · 40 blank · 18 comment · 25 complexity · afa6310197f4cd60ba934075d73a473f MD5 · raw file

  1. /**********************************************************************************************************************
  2. (c) Copyright 2012, Bret Ambrose (mailto:bretambrose@gmail.com).
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. **********************************************************************************************************************/
  14. #include "stdafx.h"
  15. #include "DatabaseProcessBase.h"
  16. #include "Interfaces/DatabaseTaskBatchInterface.h"
  17. #include "Interfaces/DatabaseConnectionInterface.h"
  18. #include "Interfaces/DatabaseEnvironmentInterface.h"
  19. #include "Interfaces/DatabaseTaskInterface.h"
  20. #include "IPShared/MessageHandling/ProcessMessageHandler.h"
  21. #include "DatabaseProcessMessages.h"
  22. using namespace IP::Db;
  23. namespace IP
  24. {
  25. namespace Execution
  26. {
  27. CDatabaseProcessBase::CDatabaseProcessBase( IDatabaseEnvironment *environment, const std::wstring &connection_string, bool process_task_results_locally, const SProcessProperties &properties ) :
  28. BASECLASS( properties ),
  29. Batches(),
  30. BatchOrdering(),
  31. PendingRequests(),
  32. NextID( static_cast< EDatabaseTaskIDType >( static_cast< uint32_t >( EDatabaseTaskIDType::INVALID ) + 1 ) ),
  33. Environment( environment ),
  34. ConnectionString( connection_string ),
  35. ProcessTaskResultsLocally( process_task_results_locally ),
  36. Connection( NULL )
  37. {
  38. FATAL_ASSERT( Environment != nullptr );
  39. }
  40. CDatabaseProcessBase::~CDatabaseProcessBase()
  41. {
  42. FATAL_ASSERT( Connection == nullptr );
  43. FATAL_ASSERT( Environment == nullptr );
  44. }
  45. void CDatabaseProcessBase::Initialize( EProcessID id )
  46. {
  47. BASECLASS::Initialize( id );
  48. Connection = Environment->Add_Connection( ConnectionString.c_str(), true );
  49. FATAL_ASSERT( Connection != nullptr );
  50. }
  51. void CDatabaseProcessBase::Cleanup( void )
  52. {
  53. FATAL_ASSERT( Environment != nullptr );
  54. BASECLASS::Cleanup();
  55. PendingRequests.clear();
  56. for ( auto iter = Batches.cbegin(); iter != Batches.end(); ++iter )
  57. {
  58. delete iter->second;
  59. }
  60. Batches.clear();
  61. BatchOrdering.clear();
  62. if ( Connection != nullptr )
  63. {
  64. Environment->Shutdown_Connection( Connection );
  65. delete Connection;
  66. Connection = nullptr;
  67. }
  68. Environment = nullptr;
  69. }
  70. void CDatabaseProcessBase::Per_Frame_Logic_End( void )
  71. {
  72. FATAL_ASSERT( Environment != nullptr );
  73. FATAL_ASSERT( Connection != nullptr );
  74. BASECLASS::Per_Frame_Logic_End();
  75. DBTaskBaseListType successes;
  76. DBTaskBaseListType failures;
  77. for ( auto iter = BatchOrdering.cbegin(), end = BatchOrdering.cend(); iter != end; ++iter )
  78. {
  79. auto batch_task_iter = Batches.find( *iter );
  80. FATAL_ASSERT( batch_task_iter != Batches.end() );
  81. IDatabaseTaskBatch *batch = batch_task_iter->second;
  82. batch->Execute_Tasks( Connection, successes, failures );
  83. }
  84. for ( auto success_iter = successes.cbegin(), end = successes.cend(); success_iter != end; ++success_iter )
  85. {
  86. IDatabaseTaskBase *task = *success_iter;
  87. auto pending_request_iter = PendingRequests.find( task->Get_ID() );
  88. FATAL_ASSERT( pending_request_iter != PendingRequests.end() );
  89. if ( ProcessTaskResultsLocally )
  90. {
  91. ( *success_iter )->On_Task_Success();
  92. }
  93. else
  94. {
  95. std::unique_ptr< const Messaging::IProcessMessage > response( new Messaging::CRunDatabaseTaskResponse( pending_request_iter->second.second, true ) );
  96. Send_Process_Message( pending_request_iter->second.first, response );
  97. }
  98. PendingRequests.erase( pending_request_iter );
  99. }
  100. for ( auto failure_iter = failures.cbegin(), end = failures.cend(); failure_iter != end; ++failure_iter )
  101. {
  102. IDatabaseTaskBase *task = *failure_iter;
  103. auto pending_request_iter = PendingRequests.find( task->Get_ID() );
  104. FATAL_ASSERT( pending_request_iter != PendingRequests.end() );
  105. if ( ProcessTaskResultsLocally )
  106. {
  107. ( *failure_iter )->On_Task_Failure();
  108. }
  109. else
  110. {
  111. std::unique_ptr< const Messaging::IProcessMessage > response( new Messaging::CRunDatabaseTaskResponse( pending_request_iter->second.second, false ) );
  112. Send_Process_Message( pending_request_iter->second.first, response );
  113. }
  114. PendingRequests.erase( pending_request_iter );
  115. }
  116. }
  117. void CDatabaseProcessBase::Register_Message_Handlers( void )
  118. {
  119. BASECLASS::Register_Message_Handlers();
  120. REGISTER_THIS_HANDLER( Messaging::CRunDatabaseTaskRequest, CDatabaseProcessBase, Handle_Run_Database_Task_Request )
  121. }
  122. uint32_t CDatabaseProcessBase::Get_Sleep_Interval_In_Milliseconds( void ) const
  123. {
  124. return 1;
  125. }
  126. void CDatabaseProcessBase::Add_Batch( IDatabaseTaskBatch *batch )
  127. {
  128. FATAL_ASSERT( batch != nullptr );
  129. Loki::TypeInfo type_info = batch->Get_Task_Type_Info();
  130. FATAL_ASSERT( Batches.find( type_info ) == Batches.end() );
  131. Batches.insert( BatchTableType::value_type( type_info, batch ) );
  132. BatchOrdering.push_back( type_info );
  133. }
  134. void CDatabaseProcessBase::Handle_Run_Database_Task_Request( EProcessID process_id, std::unique_ptr< const Messaging::CRunDatabaseTaskRequest > &message )
  135. {
  136. IDatabaseTask *task = message->Get_Task();
  137. Loki::TypeInfo hash_key( typeid( *task ) );
  138. auto iter = Batches.find( hash_key );
  139. FATAL_ASSERT( iter != Batches.end() );
  140. IP::Db::EDatabaseTaskIDType task_id = Allocate_Task_ID();
  141. task->Set_ID( task_id );
  142. iter->second->Add_Task( task );
  143. PendingRequests.insert( PendingRequestTableType::value_type( task_id, PendingRequestPairType( process_id, std::move( message ) ) ) );
  144. }
  145. EDatabaseTaskIDType CDatabaseProcessBase::Allocate_Task_ID( void )
  146. {
  147. EDatabaseTaskIDType id = NextID;
  148. NextID = static_cast< EDatabaseTaskIDType >( static_cast< uint32_t >( NextID ) + 1 );
  149. return id;
  150. }
  151. } // namespace Execution
  152. } // namespace IP