From cd71f02fad8519a47f16c00195bf9172e613bdcb Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Wed, 23 Feb 2011 17:32:21 +0000 Subject: [PATCH] Data Exchange - Implemented reconciliation options + cosmetics on synchro_exec SVN:trunk[1093] --- synchro/synchro_exec.php | 16 ++++- synchro/synchro_import.php | 3 +- synchro/synchrodatasource.class.inc.php | 78 +++++++++++++++++++------ 3 files changed, 75 insertions(+), 22 deletions(-) diff --git a/synchro/synchro_exec.php b/synchro/synchro_exec.php index 8f754d999..642ead794 100644 --- a/synchro/synchro_exec.php +++ b/synchro/synchro_exec.php @@ -138,15 +138,27 @@ try { CMDBSource::Query('START TRANSACTION'); } - $oSynchroDataSource->Synchronize($aResults, null); + $oStatLog = $oSynchroDataSource->Synchronize($aResults, null); foreach ($aResults as $sMessage) { - $oP->p("results: $sMessage"); + $oP->p($sMessage); } if ($bSimulate) { CMDBSource::Query('ROLLBACK'); } + $oP->p("Replicas: ".$oStatLog->Get('stats_nb_replica_total')); + $oP->p("Replicas touched since last synchro: ".$oStatLog->Get('stats_nb_replica_seen')); + $oP->p("Objects deleted: ".$oStatLog->Get('stats_nb_obj_deleted')); + $oP->p("Objects deletion errors: ".$oStatLog->Get('stats_nb_obj_deleted_errors')); + $oP->p("Objects obsoleted: ".$oStatLog->Get('stats_nb_obj_obsoleted')); + $oP->p("Objects obsolescence errors: ".$oStatLog->Get('stats_nb_obj_obsoleted_errors')); + $oP->p("Objects created: ".$oStatLog->Get('stats_nb_obj_created')); + $oP->p("Objects creation errors: ".$oStatLog->Get('stats_nb_obj_created_errors')); + $oP->p("Objects updated: ".$oStatLog->Get('stats_nb_obj_updated')); + $oP->p("Objects update errors: ".$oStatLog->Get('stats_nb_obj_updated_errors')); + $oP->p("Objects reconciled: ".$oStatLog->Get('stats_nb_replica_reconciled')); + $oP->p("Objects reconciliation errors: ".$oStatLog->Get('stats_nb_replica_reconciled_errors')); } } } diff --git a/synchro/synchro_import.php b/synchro/synchro_import.php index 9efb456af..95347ddfd 100644 --- a/synchro/synchro_import.php +++ b/synchro/synchro_import.php @@ -466,10 +466,11 @@ try if ($bSynchronize && !$bSimulate) { $aTraces = array(); - $oDataSource->Synchronize($aTraces, $oLoadStartDate); + $oStatLog = $oDataSource->Synchronize($aTraces, $oLoadStartDate); //echo "#@# Synchronize() returned :
\n"; //echo "
\n";
 		//print_r($aTraces);
+		//print_r($oStatLog);
 		//echo "
\n"; } diff --git a/synchro/synchrodatasource.class.inc.php b/synchro/synchrodatasource.class.inc.php index 17c754b85..145191b44 100644 --- a/synchro/synchrodatasource.class.inc.php +++ b/synchro/synchrodatasource.class.inc.php @@ -59,7 +59,7 @@ class SynchroDataSource extends cmdbAbstractObject // MetaModel::Init_AddAttribute(new AttributeString("reconciliation_list", array("allowed_values"=>null, "sql"=>"reconciliation_list", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("reconciliation_policy", array("allowed_values"=>new ValueSetEnum('use_primary_key,use_attributes'), "sql"=>"reconciliation_policy", "default_value"=>"use_attributes", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("action_on_zero", array("allowed_values"=>new ValueSetEnum('create,error'), "sql"=>"action_on_zero", "default_value"=>"create", "is_null_allowed"=>false, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeEnum("action_on_one", array("allowed_values"=>new ValueSetEnum('update,error,delete'), "sql"=>"action_on_one", "default_value"=>"update", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("action_on_one", array("allowed_values"=>new ValueSetEnum('update,error'), "sql"=>"action_on_one", "default_value"=>"update", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("action_on_multiple", array("allowed_values"=>new ValueSetEnum('take_first,create,error'), "sql"=>"action_on_multiple", "default_value"=>"error", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("delete_policy", array("allowed_values"=>new ValueSetEnum('ignore,delete,update,update_then_delete'), "sql"=>"delete_policy", "default_value"=>"ignore", "is_null_allowed"=>false, "depends_on"=>array()))); @@ -964,6 +964,7 @@ class SynchroReplica extends DBObject else { // Reconciliation could not be performed - log and EXIT + $aTraces[] = "Could not reconcile on null value: ".$sFilterCode; $this->SetLastError('Could not reconcile on null value: '.$sFilterCode); $oStatLog->Inc('stats_nb_replica_reconciled_errors'); return; @@ -971,34 +972,71 @@ class SynchroReplica extends DBObject } $oDestSet = new DBObjectSet(self::$aSearches[$oDataSource->GetKey()], array(), $aFilterValues); $iCount = $oDestSet->Count(); + $aConditions = array(); + foreach($aFilterValues as $sCode => $sValue) + { + $aConditions[] = $sCode.'='.$sValue; + } + $sConditionDesc = implode(' AND ', $aConditions); // How many objects match the reconciliation criterias switch($iCount) { case 0: - //echo "

Nothing found for: ".self::$aSearches[$oDataSource->GetKey()]->ToOQL(true, $aFilterValues)."

"; - $this->CreateObjectFromReplica($oDataSource->GetTargetClass(), $aAttributes, $oChange, $oStatLog, $aTraces); - $oStatLog->Inc('stats_nb_obj_created'); + $aTraces[] = "Nothing found on: $sConditionDesc"; + if ($oDataSource->Get('action_on_zero') == 'create') + { + $this->CreateObjectFromReplica($oDataSource->GetTargetClass(), $aAttributes, $oChange, $oStatLog, $aTraces); + } + else // assumed to be 'error' + { + $aTraces[] = "Failed to reconcile (no match)"; + $this->SetLastError('Could not find a match for reconciliation'); + $oStatLog->Inc('stats_nb_replica_reconciled_errors'); + } break; case 1: - //echo "

Found 1 for: ".self::$aSearches[$oDataSource->GetKey()]->ToOQL(true, $aFilterValues)."

"; - $oDestObj = $oDestSet->Fetch(); - $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, $aTraces, 'stats_nb_replica_reconciled'); - $this->Set('dest_id', $oDestObj->GetKey()); - $this->Set('status_dest_creator', false); - $this->Set('dest_class', get_class($oDestObj)); + $aTraces[] = "Found 1 object on: $sConditionDesc"; + if ($oDataSource->Get('action_on_one') == 'update') + { + $oDestObj = $oDestSet->Fetch(); + $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, $aTraces, 'stats_nb_replica_reconciled'); + $this->Set('dest_id', $oDestObj->GetKey()); + $this->Set('status_dest_creator', false); + $this->Set('dest_class', get_class($oDestObj)); + + $oStatLog->Inc('stats_nb_replica_reconciled'); + } + else + { + // assumed to be 'error' + $aTraces[] = "Failed to reconcile (1 match)"; + $this->SetLastError('Found a match while expecting several'); + $oStatLog->Inc('stats_nb_replica_reconciled_errors'); + } break; default: - $aConditions = array(); - foreach($aFilterValues as $sCode => $sValue) + $aTraces[] = "Found $iCount objects on: $sConditionDesc"; + if ($oDataSource->Get('action_on_multiple') == 'error') { - $aConditions[] = $sCode.'='.$sValue; + $aTraces[] = "Failed to reconcile (N>1 matches)"; + $this->SetLastError($iCount.' destination objects match the reconciliation criterias: '.$sConditionDesc); + $oStatLog->Inc('stats_nb_replica_reconciled_errors'); + } + elseif ($oDataSource->Get('action_on_multiple') == 'create') + { + $this->CreateObjectFromReplica($oDataSource->GetTargetClass(), $aAttributes, $oChange, $oStatLog, $aTraces); + } + else + { + // assumed to be 'take_first' + $oDestObj = $oDestSet->Fetch(); + $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, $aTraces, 'stats_nb_replica_reconciled'); + $this->Set('dest_id', $oDestObj->GetKey()); + $this->Set('status_dest_creator', false); + $this->Set('dest_class', get_class($oDestObj)); } - $sCondition = implode(' AND ', $aConditions); - //echo "

Found N for: ".self::$aSearches[$oDataSource->GetKey()]->ToOQL(true, $aFilterValues)."

"; - $this->SetLastError($iCount.' destination objects match the reconciliation criterias: '.$sCondition); - $oStatLog->Inc('stats_nb_replica_reconciled_errors'); } break; @@ -1033,7 +1071,7 @@ class SynchroReplica extends DBObject if (!is_null($value)) { $oDestObj->Set($sAttCode, $value); - $aValueTrace[] = "$sAttCode<$value"; + $aValueTrace[] = "$sAttCode: $value"; } } try @@ -1047,6 +1085,7 @@ class SynchroReplica extends DBObject } catch(Exception $e) { + $aTraces[] = "Failed to update destination object: {$e->getMessage()}"; $this->SetLastError('Unable to update destination object: ', $e); $oStatLog->Inc($sStatsCode.'_errors'); } @@ -1067,7 +1106,7 @@ class SynchroReplica extends DBObject if (!is_null($value)) { $oDestObj->Set($sAttCode, $value); - $aValueTrace[] = "$sAttCode<$value"; + $aValueTrace[] = "$sAttCode: $value"; } } $iNew = $oDestObj->DBInsertTracked($oChange); @@ -1083,6 +1122,7 @@ class SynchroReplica extends DBObject } catch(Exception $e) { + $aTraces[] = "Failed to create $sClass ({$e->getMessage()})"; $this->SetLastError('Unable to create destination object: ', $e); $oStatLog->Inc('stats_nb_obj_created_errors'); }