Compensation for BUILD_START, BUILD_SUCCESS, BUILD_UNCHANGED 67/112967/2
authorJunghyun Kim <jh0822.kim@samsung.com>
Fri, 3 Feb 2017 11:52:05 +0000 (20:52 +0900)
committerJunghyun Kim <jh0822.kim@samsung.com>
Mon, 6 Feb 2017 08:14:39 +0000 (00:14 -0800)
PROBLEM:
- Since obs-2.7, all events are gathered to src_server.
- src_server delivers all notify events to plugins
- There is possibility that BUILD_SUCCESS has been processed before
  BUILD_START is processed.

SOLUTION:
- For BUILD_SUCCESS, BUILD_FAILED and BUILD_UNCHANGED,
  it is recorded even if there is no row for this build.
- For BUILD_START, it updates to prior BUILD_SUCCESS data
  if time is prior to the time of BUILD_SUCCESS.

Change-Id: Ifcc48504e23679ee3a9518f37f1ea21f35237020
Signed-off-by: Junghyun Kim <jh0822.kim@samsung.com>
BuildMonitorDB.pm

index c99a65a..ad57c3c 100644 (file)
@@ -37,6 +37,8 @@ my $package_build_finished_sth;
 my $search_not_succeeded_packages_sth;
 my $build_status_sth;
 my $build_status_exists_sth;
+my $check_prior_to_build_success_sth;
+my $update_build_start_time_sth;
 my $package_disable_last_flag_sth;
 my $insert_package_build_if_not_exist_sth;
 my $package_build_status_sth;
@@ -138,6 +140,33 @@ sub check_proj_pattern {
 
   return 0;
 }
+
+sub check_prior_to_build_success {
+  my ($build_project_id, $build_target_id, $info_package_id, $package_build_time) = @_;
+
+  $check_prior_to_build_success_sth->execute($build_project_id, $build_target_id,
+    $info_package_id, $package_build_time);
+
+  my $arr_ref = $check_prior_to_build_success_sth->fetchrow_arrayref;
+  if( ! $arr_ref ) {
+    # if not found, return 0.
+    return 0;
+  }
+
+  my $bpa_id = @$arr_ref[0];
+
+  print "[", __LINE__, "] returning bpa_id = $bpa_id\n";
+
+  # return bpa.id
+  return $bpa_id;
+}
+
+sub update_build_start_time {
+  my ($bpa_id, $package_build_time) = @_;
+
+  $update_build_start_time_sth->execute($package_build_time, $bpa_id);
+}
+
 #-------------------------------------------------------------------------------
 # event handlers
 #-------------------------------------------------------------------------------
@@ -1252,17 +1281,27 @@ sub package_build_start {
   } else {
     $reason=parse_reason($reason);
   }
+  $reason = substr($reason, 0, 1000);
 
   my $state = "Building";
   my $project_build_time = $time;
   my $package_build_time = $project_build_time;
 
-  # start the project build if this is the first building of a package in this project.
-  project_build_start($build_project_id, $proj_name, $repo, $arch, $state, $project_build_time);
+  # At first, we need to check this BUILD_START is an event that should be processed before BUILD_SUCCESS.
   my $build_target_id=get_build_target_id($build_project_id, $repo, $arch);
-  insert_package_build($build_target_id, $info_package_id);
-  print "[", __LINE__, "][package_build_start($package_name)] $reason, $build_target_id, $info_package_id, $build_log_url\n";
-  $package_build_start_sth->execute($package_build_time, $state, $reason, $build_log_url, $build_target_id, $info_package_id);
+  print "[", __LINE__, "] $build_project_id, $build_target_id, $info_package_id, $package_build_time\n";
+  if( my $bpa_id = check_prior_to_build_success($build_project_id, $build_target_id, $info_package_id, $package_build_time) ) {
+    print "[", __LINE__, "] update build time only!!! $bpa_id, $package_build_time\n";
+    update_build_start_time($bpa_id, $package_build_time);
+  } else {
+    # start the project build if this is the first building of a package in this project.
+    project_build_start($build_project_id, $proj_name, $repo, $arch, $state, $project_build_time);
+    $build_target_id=get_build_target_id($build_project_id, $repo, $arch);
+
+    insert_package_build($build_target_id, $info_package_id);
+    print "[", __LINE__, "][package_build_start($package_name)] $reason, $build_target_id, $info_package_id, $build_log_url\n";
+    $package_build_start_sth->execute($package_build_time, $state, $reason, $build_log_url, $build_target_id, $info_package_id);
+  }
 
   my $elapsed_time = get_cur_time() - $start_time;
   print "[",__LINE__,"] took $elapsed_time seconds.\n";
@@ -1305,7 +1344,7 @@ sub insert_package_build {
 
 #-------------------------------------------------------------------------------
 sub insert_package_build_if_not_exist {
-  my ($build_target_id, $repo, $arch, $info_package_id, $current_status) = @_;
+  my ($build_target_id, $info_package_id, $current_status) = @_;
 
   $check_package_build_sth->execute($build_target_id, $info_package_id);
   my $arr_ref = $check_package_build_sth->fetchrow_arrayref;
@@ -1421,7 +1460,7 @@ sub package_build_status {
   }
 
   # if no row for this package_build. insert a row.
-  my $affected_rows = insert_package_build_if_not_exist($build_target_id, $repo, $arch, $info_package_id, $status);
+  my $affected_rows = insert_package_build_if_not_exist($build_target_id, $info_package_id, $status);
 
   if( $affected_rows == 0 ) {
     if( $status eq "broken" ) {
@@ -1589,18 +1628,37 @@ sub package_build_finished {
     return;
   }
 
-  if ( $package_name =~ ".*_aggregate") {
+  # Since _aggregate packages does not trigger BUILD_START, it always calls package_build_start().
+  if ( $package_name =~ ".*_aggregate" ) {
     package_build_start("test", $projid, $repo, $arch, $package_name, $time);
   }
+
   my $build_target_id=get_build_target_id($build_project_id, $repo, $arch);
   print "[", __LINE__, "][package_build_finished($package_name)] $pre_install_time, $install_time, $main_build_time, $status, $build_target_id, $repo, $arch, $info_package_id\n";
-  eval {
-    $g_dbh->begin_work();
-    $package_build_finished_sth->execute($time, $pre_install_time, $install_time, $main_build_time, "$status", "$detail", $build_target_id, $info_package_id);
-    $g_dbh->commit();
-  };
-  if($@) {
-    warn "[", __LINE__, "] Transaction aborted because $@\n";
+  my $transaction_aborted = 1;
+  while( $transaction_aborted ) {
+    $transaction_aborted = 0;
+    eval {
+      $g_dbh->begin_work();
+
+      # if there is no 'Building' rows, insert a row.
+      # This happens when BUILD_SUCCESS is processed before BUILD_START is processed.
+      if( insert_package_build_if_not_exist($build_target_id, $info_package_id, 'Building') ) {
+        my $state = "Building";
+        my $reason = "";
+        my $build_log_url = "";
+
+        print "[", __LINE__, "][NO_BUILDING! package_build_start($package_name)] $reason, $build_target_id, $info_package_id, $build_log_url\n";
+        $package_build_start_sth->execute(1, $state, $reason, $build_log_url, $build_target_id, $info_package_id);
+      }
+
+      $package_build_finished_sth->execute($time, $pre_install_time, $install_time, $main_build_time, "$status", "$detail", $build_target_id, $info_package_id);
+      $g_dbh->commit();
+    };
+    if($@) {
+      $transaction_aborted = 1;
+      warn "[", __LINE__, "] Transaction aborted because $@\n";
+    }
   }
 
   if( $status eq 'failed' ) {
@@ -1744,6 +1802,26 @@ sub connect_db {
   my $build_status_exists_sql = qq/SELECT bp.id FROM build_project bp, build_target bt, build_package bpa WHERE bp.id = bt.build_project_id AND bpa.build_target_id = bt.id AND bp.id = ?  AND bt.repository = ?  AND bt.arch = ?  AND bpa.info_package_id = ? LIMIT 1;/;
   $build_status_exists_sth = $g_dbh->prepare($build_status_exists_sql);
 
+  my $check_prior_to_build_success_sql =
+qq/
+SELECT bpa.id
+FROM build_project bp, build_target bt, build_package bpa
+WHERE bt.build_project_id = bp.id
+AND bpa.build_target_id = bt.id
+AND bp.id = ?
+AND bt.id = ?
+AND bpa.info_package_id = ?
+AND bpa.end_time > FROM_UNIXTIME(?)
+AND bpa.start_time = FROM_UNIXTIME(1)
+/;
+  $check_prior_to_build_success_sth = $g_dbh->prepare($check_prior_to_build_success_sql);
+
+  my $update_build_start_time_sql =
+qq/
+UPDATE build_package SET start_time=FROM_UNIXTIME(?) WHERE id=?
+/;
+  $update_build_start_time_sth = $g_dbh->prepare($update_build_start_time_sql);
+
   #-----------------------------------------------------------------------------
   # build_project TABLE
   my $get_build_project_id_sql=qq/SELECT id FROM build_project WHERE info_project_id=? ORDER BY id DESC LIMIT 1;/;