From patchwork Thu Jan 7 19:38:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Jackson X-Patchwork-Id: 7979481 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 37B2ABEEE5 for ; Thu, 7 Jan 2016 19:42:00 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4A20220107 for ; Thu, 7 Jan 2016 19:41:59 +0000 (UTC) Received: from lists.xen.org (lists.xenproject.org [50.57.142.19]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6D4432013D for ; Thu, 7 Jan 2016 19:41:58 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aHGOG-0003Tu-Ue; Thu, 07 Jan 2016 19:38:32 +0000 Received: from mail6.bemta4.messagelabs.com ([85.158.143.247]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aHGOF-0003SS-RJ for xen-devel@lists.xenproject.org; Thu, 07 Jan 2016 19:38:31 +0000 Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id 47/E7-08977-7BEBE865; Thu, 07 Jan 2016 19:38:31 +0000 X-Env-Sender: prvs=807bdda5f=Ian.Jackson@citrix.com X-Msg-Ref: server-3.tower-21.messagelabs.com!1452195506!8498330!2 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 7.35.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 22697 invoked from network); 7 Jan 2016 19:38:28 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-3.tower-21.messagelabs.com with RC4-SHA encrypted SMTP; 7 Jan 2016 19:38:28 -0000 X-IronPort-AV: E=Sophos;i="5.20,534,1444694400"; d="scan'208";a="323534838" From: Ian Jackson To: Date: Thu, 7 Jan 2016 19:38:14 +0000 Message-ID: <1452195496-16016-6-git-send-email-ian.jackson@eu.citrix.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1452195496-16016-1-git-send-email-ian.jackson@eu.citrix.com> References: <1452195496-16016-1-git-send-email-ian.jackson@eu.citrix.com> MIME-Version: 1.0 X-DLP: MIA2 Cc: Ian Jackson , Ian Campbell Subject: [Xen-devel] [OSSTEST PATCH 5/7] Database locking: Tcl: for errorCode, use pg_exec, not pg_execute X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We would like to be able to retry db transactions. To do this we need to know why they failed (if they did). But pg_execute does not set errorCode. (This is clearly a bug.) And since it immediately discards a failed statement, any error information has been lost by the time pg_execute returns. So, instead, use pg_exec, and manually mess about with fishing suitable information out of a failed statement handle, and generating an appropriate errorCode. There are no current consumers of this errorCode: that will come in a moment. A wrinkle is that as a result it is no longer possible to use db-execute on a SELECT statement nor db-execute-array on a non-SELECT statement. This is because the 1. the `ok' status that we have to check for is different for statements which are commands and ones which return tupes and 2. we need to fish a different return value out of the statement handle (-cmdTuples vs -numTuples). But all uses in the codebase are now fine for this distinction. Signed-off-by: Ian Jackson --- tcl/JobDB-Executive.tcl | 54 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/tcl/JobDB-Executive.tcl b/tcl/JobDB-Executive.tcl index bbce6fc..ed9abbb 100644 --- a/tcl/JobDB-Executive.tcl +++ b/tcl/JobDB-Executive.tcl @@ -121,13 +121,61 @@ proc db-execute-debug {stmt} { puts stderr "EXECUTING >$stmt<" } } + +proc db--exec-check {shvar stmt expected_status body} { + # pg_execute does not set errorCode and it throws away the + # statement handle so we can't get the error out. So + # use pg_exec, as wrapped up here. + + # db--exec-check executes stmt and checks that the status is + # `expected_status'. If OK, executes body with $shvar set to the + # stmt handle. Otherwise throws with errorCode + # {OSSTEST-PSQL } + + global errorInfo errorCode + upvar 1 $shvar sh + + set sh [pg_exec dbh $stmt] + + set rc [catch { + set status [pg_result $sh -status] + if {[string compare $status $expected_status]} { + set emsg [pg_result $sh -error] + set sqlstate [pg_result $sh -error sqlstate] + if {![string length $emsg]} { + set emsg "osstest expected status $expected_status got $status" + } + set context [pg_result $sh -error context] + error $emsg \ + " while executing SQL\n$stmt\n in SQL context\n$context" \ + [list OSSTEST-PSQL $status $sqlstate] + } + uplevel 1 $body + } emsg] + + set ei $errorInfo + set ec $errorCode + catch { pg_result $sh -clear } + + return -code $rc -errorinfo $ei -errorcode $ec $emsg +} + proc db-execute {stmt} { db-execute-debug $stmt - uplevel 1 [list pg_execute dbh $stmt] + db--exec-check sh $stmt PGRES_COMMAND_OK { + return [pg_result $sh -cmdTuples] + } } -proc db-execute-array {arrayvar stmt args} { +proc db-execute-array {arrayvar stmt {body {}}} { db-execute-debug $stmt - uplevel 1 [list pg_execute -array $arrayvar dbh $stmt] $args + db--exec-check sh $stmt PGRES_TUPLES_OK { + set nrows [pg_result $sh -numTuples] + for {set row 0} {$row < $nrows} {incr row} { + uplevel 1 [list pg_result $sh -tupleArray $row $arrayvar] + uplevel 1 $body + } + return $nrows + } } proc lock-tables {tables} {