512 lines
15 KiB
C++
512 lines
15 KiB
C++
#include "stdafx.h"
|
|
#include "BatchProcessor.h"
|
|
|
|
#if DBPROXY_TYPE_SELECTOR == DBPROXY_TYPE_UNIT
|
|
#if !defined(_JAPAN)
|
|
#ifdef _NA000000_110218_RANK_REPORTER_IN_DBUNIT
|
|
#include "VersionControl.h"
|
|
#include "SCItemSlot.h"
|
|
|
|
#define BATCHUNIT_REGISTERING_MARK
|
|
#include "./RankReportUpdateUnit.hxx"
|
|
#undef BATCHUNIT_REGISTERING_MARK
|
|
|
|
#include "./BatchUnitFactory.hxx"
|
|
|
|
#define REF_LOGIC_FOR_RANK_REPORT (0)
|
|
|
|
//==================================================================================================
|
|
// implements
|
|
|
|
namespace batch_unit {
|
|
|
|
using batch::IBatchUnit;
|
|
|
|
void
|
|
RankReportUpdateUnit::UpdateNode::Init()
|
|
{
|
|
ZeroMemory(this, sizeof(*this));
|
|
util::LList::Init(this);
|
|
}
|
|
|
|
RankReportUpdateUnit::RankReportUpdateUnit()
|
|
: unit_type_(0)
|
|
, select_query_string_(NULL)
|
|
, update_query_string_(NULL)
|
|
, step_(STEP_NONE)
|
|
, total_completed_(false)
|
|
, suspend_select_query_(false)
|
|
, completed_update_query_(false)
|
|
{
|
|
const DWORD UserSlotLastKey = 100;
|
|
BOOST_STATIC_ASSERT(kPending_StartKey < UserSlotLastKey);
|
|
select_key_generator_.Create(kPending_StartKey, UserSlotLastKey);
|
|
|
|
max_transactions_ = GetPrivateProfileInt("DBPUNIT_DATA",
|
|
"MAX_UPDATES_PER_UNITTIME",
|
|
300,
|
|
"./DBPUnit.ini");
|
|
if (max_transactions_ < 300)
|
|
max_transactions_ = 300;
|
|
update_key_generator_.Create(kPending_StartKey, max_transactions_);
|
|
|
|
ZeroMemory(&arguments_, sizeof(arguments_));
|
|
util::LList::Init(&arguments_.pending_nodes_);
|
|
util::LList::Init(&arguments_.updating_nodes_);
|
|
ZeroMemory(&statistics_, sizeof(statistics_));
|
|
ZeroMemory(&rank_info_, sizeof(rank_info_));
|
|
}
|
|
|
|
RankReportUpdateUnit::~RankReportUpdateUnit()
|
|
{
|
|
}
|
|
|
|
void RankReportUpdateUnit::SetUnitType(int unit_type)
|
|
{
|
|
if (false) {
|
|
}
|
|
else if (unit_type == BatchunitFactory::RANK_REPORT_INVENTORY)
|
|
{
|
|
select_query_string_ = "{call USP_GetItemListForInven(%d, ?)}";
|
|
update_query_string_ =
|
|
"{call USP_SetRankReportForInven(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}";
|
|
}
|
|
else if (unit_type == BatchunitFactory::RANK_REPORT_WAREHOUSE)
|
|
{
|
|
select_query_string_ = "{call USP_GetItemListForWare(%d, ?)}";
|
|
update_query_string_ =
|
|
"{call USP_SetRankReportForWare(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}";
|
|
}
|
|
else if (unit_type == BatchunitFactory::RANK_REPORT_GUILD_WAREHOUSE)
|
|
{
|
|
select_query_string_ = "{call USP_GetItemListForGuildWare(%d, ?)}";
|
|
update_query_string_ =
|
|
"{call USP_SetRankReportForGuildWare(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}";
|
|
}
|
|
}
|
|
|
|
inline IBatchUnit::eSTEP
|
|
RankReportUpdateUnit::CurrentStep() const
|
|
{
|
|
return step_;
|
|
}
|
|
|
|
BOOLEAN
|
|
RankReportUpdateUnit::BatchInit()
|
|
{
|
|
SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"]\n");
|
|
|
|
ZeroMemory(&arguments_, sizeof(arguments_));
|
|
util::LList::Init(&arguments_.pending_nodes_);
|
|
util::LList::Init(&arguments_.updating_nodes_);
|
|
|
|
timer_.SetTimer(300);
|
|
statistics_timer_.SetTimer(5000);
|
|
step_ = this->STEP_PROCESSING;
|
|
|
|
SUNLOG(eCRITICAL_LOG, "|ChangeUnitType|GetQuery=%s|SetQuery=%s|",
|
|
select_query_string_, update_query_string_);
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOLEAN
|
|
RankReportUpdateUnit::BatchProcess()
|
|
{
|
|
if (timer_.IsExpired() == false)
|
|
return true;
|
|
|
|
//printf("["__FUNCTION__"]\n");
|
|
|
|
SelectItemList();
|
|
UpdateRankReport();
|
|
|
|
bool forced_statistics_logging = false;
|
|
// completion check
|
|
if (completed_update_query_)
|
|
{
|
|
if (util::LList::IsEmpty(&arguments_.pending_nodes_) &&
|
|
util::LList::IsEmpty(&arguments_.updating_nodes_) &&
|
|
this->max_transactions_ == update_key_generator_.GetSize()) // to fit dual buffering db queue
|
|
{
|
|
total_completed_ = true;
|
|
forced_statistics_logging = true;
|
|
}
|
|
};
|
|
if (forced_statistics_logging || statistics_timer_.IsExpired())
|
|
{
|
|
float interval = static_cast<float>(statistics_timer_.GetInterval());
|
|
; interval /= 1000.0f;
|
|
|
|
float selecting_ratio = statistics_.solved_selectings_ / interval;
|
|
float updating_ratio = statistics_.solving_updatings_ / interval;
|
|
|
|
SUNLOG(eCRITICAL_LOG,
|
|
"|Number of get queried=%u|Number of set queried=%u|",
|
|
statistics_.number_of_get_queried_, statistics_.number_of_set_queried_);
|
|
|
|
SUNLOG(eCRITICAL_LOG,
|
|
"|Pendings=%d|Updatings=%d|gets/sec=%2.2f|sets/sec=%2.2f|",
|
|
arguments_.number_of_pending_nodes_, arguments_.number_of_updating_nodes_,
|
|
selecting_ratio, updating_ratio);
|
|
|
|
statistics_.solved_selectings_ = 0;
|
|
statistics_.solving_updatings_ = 0;
|
|
}
|
|
|
|
BOOLEAN continued = true;
|
|
if (total_completed_)
|
|
{
|
|
continued = false;
|
|
step_ = this->STEP_COMPLETED;
|
|
}
|
|
|
|
return continued;
|
|
}
|
|
|
|
BOOLEAN
|
|
RankReportUpdateUnit::BatchRelease()
|
|
{
|
|
printf("["__FUNCTION__"]\n");
|
|
//for (PendingNode* it = pending_nodes_;
|
|
// it != &pending_nodes_[_countof(pending_nodes_)];
|
|
// ++it)
|
|
//{
|
|
// SAFE_DELETE(it->character_);
|
|
// ZeroMemory(it, sizeof(*it));
|
|
//}
|
|
step_ = this->STEP_RELEASED;
|
|
//
|
|
delete this; // don't implement after at this point
|
|
//
|
|
return true;
|
|
}
|
|
|
|
void
|
|
RankReportUpdateUnit::DBResult(DWORD index, QueryResult* query_result)
|
|
{
|
|
BOOST_STATIC_ASSERT(sizeof(KeyNode) == sizeof(index));
|
|
KeyNode key_node = { 0, };
|
|
key_node.composed_ = index;
|
|
|
|
switch (key_node.query_type_)
|
|
{
|
|
case key_node.QUERY_SELECT_ITEMLIST:
|
|
{
|
|
SelectedItemList(key_node, query_result);
|
|
}
|
|
break;
|
|
case key_node.QUERY_UPDATE_RANKREPORT:
|
|
{
|
|
UpdatedRankReport(key_node, query_result);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
}; //end of namespace 'batch_unit'
|
|
//
|
|
//
|
|
//==================================================================================================
|
|
//
|
|
//
|
|
namespace batch_unit {
|
|
;
|
|
|
|
BOOLEAN
|
|
RankReportUpdateUnit::SelectItemList()
|
|
{
|
|
if (completed_update_query_ != false) {
|
|
return false;
|
|
}
|
|
|
|
if (arguments_.total_pages_ != 0 &&
|
|
arguments_.selected_page_ >= arguments_.total_pages_)
|
|
{
|
|
completed_update_query_ = true;
|
|
return false;
|
|
}
|
|
|
|
if (suspend_select_query_ != false) {
|
|
return false;
|
|
}
|
|
|
|
if (select_key_generator_.IsEmpty() != false) {
|
|
return false; // wait next time
|
|
}
|
|
|
|
const DWORD user_slot_index = select_key_generator_.GetKey();
|
|
|
|
++arguments_.selected_page_;
|
|
|
|
STRING_SAFER_QUERY128 query_buffer;
|
|
query_buffer.MakeString(select_query_string_, arguments_.selected_page_);
|
|
|
|
Query_GetItemList* query = Query_GetItemList::ALLOC();
|
|
KeyNode key_node = { 0, };
|
|
key_node.query_type_ = key_node.QUERY_SELECT_ITEMLIST;
|
|
key_node.node_key_ = static_cast<WORD>(user_slot_index);
|
|
query->SetVoidObject(this);
|
|
query->SetIndex(key_node.composed_);
|
|
query->SetQuery(query_buffer);
|
|
query->SetQueriedPage(arguments_.selected_page_);
|
|
if (Query_GetItemList::sQUERY_PARAM* parameter = &query->parameter_[0]) {
|
|
parameter->query_page = arguments_.selected_page_;
|
|
};
|
|
|
|
SolarDatabaseInDBP* first_db = g_DBProxyServer.Get1stDatabase();
|
|
first_db->DBQuery(query);
|
|
|
|
return false;
|
|
}
|
|
|
|
BOOLEAN
|
|
RankReportUpdateUnit::SelectedItemList(const KeyNode& index, QueryResult* query_result_base)
|
|
{
|
|
select_key_generator_.RestoreKey(index.node_key_);
|
|
|
|
++statistics_.number_of_get_queried_;
|
|
++statistics_.solved_selectings_;
|
|
|
|
Query_GetItemList* const query_result = static_cast<Query_GetItemList*>(query_result_base);
|
|
const DWORD number_of_rows = query_result->GetResultRowNum();
|
|
|
|
if (number_of_rows == 0)
|
|
{
|
|
MakeUpdateQuery(0, false);
|
|
MakeUpdateQuery(0, true);
|
|
rank_info_.guid = 0;
|
|
Query_GetItemList::FREE(query_result);
|
|
// force stop
|
|
completed_update_query_ = true;
|
|
return false;
|
|
}
|
|
|
|
// latest update
|
|
arguments_.total_pages_ = query_result->parameter_[0].end_page;
|
|
|
|
const ItemInfoParser* item_parser = ItemInfoParser::Instance();
|
|
// working variables
|
|
ITEMPART item_part;
|
|
ITEMSTREAMEX item_stream, result_item_stream;
|
|
eRANK convert_result_rank = RANK_E;
|
|
int converted_version;
|
|
//
|
|
DWORD row = 0;
|
|
for (; row < number_of_rows; ++row)
|
|
{
|
|
const Query_GetItemList::sQUERY_RESULT& result = query_result->query_result_[row];
|
|
const SLOTCODE item_code = static_cast<SLOTCODE>(result.item_code);
|
|
if (result.item_code == 0) {
|
|
continue;
|
|
};
|
|
#if SUN_CODE_BACKUP
|
|
// NOTE: f110304.1L, added 2nd filter rule to reward a missing items
|
|
if (result.item_code < 32768) {
|
|
continue;
|
|
}
|
|
#endif
|
|
const BASE_ITEMINFO* item_info = item_parser->GetItemInfo(item_code);
|
|
if (item_info == NULL) {
|
|
continue;
|
|
}
|
|
|
|
;{ // make item_part without serial
|
|
ZeroMemory(&item_part, sizeof(item_part));
|
|
item_part.wCode = item_code;
|
|
item_part.byDura = static_cast<DURATYPE>(result.dura_or_num);
|
|
};
|
|
;{ // make item stream
|
|
item_stream.Part = item_part;
|
|
CopyMemory(&item_stream.OptionPart, result.option_stream,
|
|
sizeof(item_stream.OptionPart));
|
|
};
|
|
|
|
// interfaces for _NA000000_110218_RANK_REPORTER_IN_DBUNIT
|
|
// = { SCItemSlot::ClearConvertResult, SCItemSlot::GetConvertResult }
|
|
SCItemSlot::ClearConvertResult();
|
|
bool converted = VersionControl::ConvertItem(&converted_version, &result_item_stream,
|
|
result.version, &item_stream);
|
|
if (converted == false) {
|
|
continue;
|
|
}
|
|
if (SCItemSlot::GetConvertResult(&convert_result_rank) == false) {
|
|
continue;
|
|
};
|
|
if (rank_info_.guid == 0) {
|
|
rank_info_.guid = result.guid;
|
|
};
|
|
bool update_current_guid = (rank_info_.guid != result.guid);
|
|
if (update_current_guid)
|
|
{
|
|
// ACTION: insert query & refresh
|
|
MakeUpdateQuery(result.guid, false);
|
|
MakeUpdateQuery(result.guid, true);
|
|
}
|
|
rank_info_.guid = result.guid;
|
|
// update result information
|
|
if (item_info->IsAccessory() || item_info->IsSpecialAccessory()) {
|
|
++rank_info_.accessory_ranks[convert_result_rank];
|
|
}
|
|
else {
|
|
++rank_info_.ranks[convert_result_rank];
|
|
}
|
|
//
|
|
}
|
|
|
|
Query_GetItemList::FREE(query_result);
|
|
|
|
// update remained last record in chunked page
|
|
if (arguments_.total_pages_ != 0 &&
|
|
arguments_.selected_page_ >= arguments_.total_pages_)
|
|
{
|
|
MakeUpdateQuery(0, false);
|
|
MakeUpdateQuery(0, true);
|
|
rank_info_.guid = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RankReportUpdateUnit::MakeUpdateQuery(int new_guid, bool is_accessory)
|
|
{
|
|
__UNUSED(new_guid);
|
|
;{
|
|
const short* it = is_accessory ?
|
|
&rank_info_.accessory_ranks[RANK_D] :
|
|
&rank_info_.ranks[RANK_D];
|
|
|
|
const short* end = is_accessory ?
|
|
&rank_info_.accessory_ranks[_countof(rank_info_.accessory_ranks)] :
|
|
&rank_info_.ranks[_countof(rank_info_.ranks)];
|
|
|
|
for ( ; it != end; ++it)
|
|
{
|
|
if (*it != 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (it == end) {
|
|
return false;
|
|
}
|
|
};
|
|
// ACTION: insert query & refresh
|
|
|
|
//if (need_update_check != 0)
|
|
UpdateNode* update_node = TAllocNew(UpdateNode);
|
|
update_node->Init();
|
|
//update_node->key_ = update_key_generator_.GetKey(); //assert key_ != 0
|
|
update_node->query_ = Query_SetRankReport::ALLOC();
|
|
// alignment processed values
|
|
|
|
short* src_ptr = is_accessory ? rank_info_.accessory_ranks : rank_info_.ranks;
|
|
Query_SetRankReport* query = update_node->query_;
|
|
if (Query_SetRankReport::sQUERY_PARAM* parameter = &query->parameter_[0]) {
|
|
parameter->guid = rank_info_.guid;
|
|
BOOST_STATIC_ASSERT(sizeof(parameter->rank_array[0]) == sizeof(rank_info_.ranks[0]) &&
|
|
sizeof(parameter->rank_array) == sizeof(rank_info_.ranks) &&
|
|
sizeof(rank_info_.ranks) == sizeof(rank_info_.accessory_ranks));
|
|
CopyMemory(parameter->rank_array, src_ptr, sizeof(parameter->rank_array));
|
|
parameter->rank_array[0] = is_accessory;
|
|
}
|
|
//
|
|
util::LList::AddPrev(update_node, &arguments_.pending_nodes_);
|
|
++arguments_.number_of_pending_nodes_;
|
|
// clear accumulators
|
|
ZeroMemory(src_ptr, sizeof(rank_info_.ranks));
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOLEAN
|
|
RankReportUpdateUnit::UpdateRankReport()
|
|
{
|
|
UpdateNode* it = static_cast<UpdateNode*>(arguments_.pending_nodes_.next);
|
|
for (; it != &arguments_.pending_nodes_;)
|
|
{
|
|
if (update_key_generator_.IsEmpty()) {
|
|
return false;
|
|
}
|
|
|
|
UpdateNode* extracted = it;
|
|
it = util::LList::Delete(it);
|
|
if (arguments_.number_of_pending_nodes_)
|
|
--arguments_.number_of_pending_nodes_;
|
|
|
|
extracted->key_ = update_key_generator_.GetKey();
|
|
|
|
Query_SetRankReport* const query = extracted->query_;
|
|
query->node_pointer_ = extracted; // passing object;
|
|
|
|
util::LList::AddPrev(extracted, &arguments_.updating_nodes_);
|
|
++arguments_.number_of_updating_nodes_;
|
|
|
|
// query { update AC info };
|
|
const Query_SetRankReport::sQUERY_PARAM* parameter = &query->parameter_[0];
|
|
|
|
STRING_SAFER_QUERY128 query_buffer;
|
|
query_buffer.MakeString(update_query_string_);
|
|
|
|
KeyNode key_node = { 0, };
|
|
key_node.query_type_ = key_node.QUERY_UPDATE_RANKREPORT;
|
|
key_node.node_key_ = static_cast<WORD>(extracted->key_);
|
|
query->SetVoidObject(this);
|
|
query->SetIndex(key_node.composed_);
|
|
query->SetQuery(query_buffer);
|
|
|
|
SolarDatabaseInDBP* second_db = g_DBProxyServer.Get2ndDatabase();
|
|
second_db->DBQuery(query);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOLEAN
|
|
RankReportUpdateUnit::UpdatedRankReport(const KeyNode& index, QueryResult* query_result_base)
|
|
{
|
|
update_key_generator_.RestoreKey(index.node_key_);
|
|
|
|
++statistics_.number_of_set_queried_;
|
|
//static int queried = 0;
|
|
//printf("Number of queried=%u\n", ++queried);
|
|
|
|
Query_SetRankReport* const query_result = static_cast<Query_SetRankReport*>(query_result_base);
|
|
|
|
UpdateNode* update_node = reinterpret_cast<UpdateNode*>(query_result->node_pointer_);
|
|
util::LList::Delete(update_node);
|
|
|
|
if (arguments_.number_of_updating_nodes_)
|
|
--arguments_.number_of_updating_nodes_;
|
|
|
|
++statistics_.solving_updatings_;
|
|
//printf("Updated %s\n", query_result->GetQuery());
|
|
|
|
TAllocDelete(UpdateNode, update_node);
|
|
Query_SetRankReport::FREE(query_result);
|
|
|
|
// balance formula
|
|
size_t remains = update_key_generator_.GetSize();
|
|
suspend_select_query_ = remains < 10 ||
|
|
(MAX_GET_ITEM_ROWS_PER_PAGE * 7) < arguments_.number_of_pending_nodes_;
|
|
|
|
return true;
|
|
}
|
|
|
|
}; //end of namespace 'batch_unit'
|
|
//
|
|
//
|
|
//==================================================================================================
|
|
//
|
|
//
|
|
namespace batch_unit {
|
|
;
|
|
|
|
|
|
}; //end of namespace 'batch_unit'
|
|
//
|
|
//==================================================================================================
|
|
#endif //_NA000000_110218_RANK_REPORTER_IN_DBUNIT
|
|
#endif //!defined(_JAPAN)
|
|
#endif //DBPROXY_TYPE_SELECTOR == DBPROXY_TYPE_UNIT
|
|
|