db.py 6.98 KB
Newer Older
Jean-Paul Smets's avatar
Jean-Paul Smets committed
1
##############################################################################
Kevin Deldycke's avatar
Kevin Deldycke committed
2
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
3 4
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
Kevin Deldycke's avatar
Kevin Deldycke committed
5
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
6 7
# Copyright (c) Digital Creations.  All rights reserved.
# Copyright (c) Nexedi SARL 2004.  All rights reserved.
Kevin Deldycke's avatar
Kevin Deldycke committed
8
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
9
# This license has been certified as Open Source(tm).
Kevin Deldycke's avatar
Kevin Deldycke committed
10
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
11 12 13
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
Kevin Deldycke's avatar
Kevin Deldycke committed
14
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
15 16
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
Kevin Deldycke's avatar
Kevin Deldycke committed
17
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
18 19 20 21
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
Kevin Deldycke's avatar
Kevin Deldycke committed
22
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
23 24 25 26 27 28 29
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
Kevin Deldycke's avatar
Kevin Deldycke committed
30
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
31 32 33
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
Kevin Deldycke's avatar
Kevin Deldycke committed
34
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
35 36 37
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
Kevin Deldycke's avatar
Kevin Deldycke committed
38
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
39 40 41
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
Kevin Deldycke's avatar
Kevin Deldycke committed
42
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
43 44 45
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
Kevin Deldycke's avatar
Kevin Deldycke committed
46
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
47 48
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
Kevin Deldycke's avatar
Kevin Deldycke committed
49
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
50 51 52
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
Kevin Deldycke's avatar
Kevin Deldycke committed
53
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
54 55
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
Kevin Deldycke's avatar
Kevin Deldycke committed
56
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
57 58 59 60 61 62
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
Kevin Deldycke's avatar
Kevin Deldycke committed
63 64
#
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
65
# Disclaimer
Kevin Deldycke's avatar
Kevin Deldycke committed
66
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
67 68 69 70 71 72 73 74 75 76 77 78
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
Kevin Deldycke's avatar
Kevin Deldycke committed
79 80
#
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
81 82 83
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
Kevin Deldycke's avatar
Kevin Deldycke committed
84
#
Jean-Paul Smets's avatar
Jean-Paul Smets committed
85 86 87 88 89 90 91 92 93 94
##############################################################################

from Products.ZMySQLDA.db import *

class DeferredDB(DB):
    """
        An experimental MySQL DA which implements deferred execution
        of SQL code in order to reduce locks and provide better behaviour
        with MyISAM non transactional tables
    """
Kevin Deldycke's avatar
Kevin Deldycke committed
95

Jean-Paul Smets's avatar
Jean-Paul Smets committed
96 97 98
    def __init__(self,connection):
        DB.__init__(self, connection)
        self.sql_string_list = []
Kevin Deldycke's avatar
Kevin Deldycke committed
99

Jean-Paul Smets's avatar
Jean-Paul Smets committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
    def query(self,query_string, max_rows=1000):
        self._use_TM and self._register()
        desc=None
        result=()
        db=self.db
        try:
            self._lock.acquire()
            for qs in filter(None, map(strip,split(query_string, '\0'))):
                qtype = upper(split(qs, None, 1)[0])
                if qtype == "SELECT":
                      raise NotSupportedError, "can not SELECT in deferred connections"
                #LOG('ZMySQLDDA', 0, "insert string %s" % qs )
                self.sql_string_list.append(qs)
        finally:
            self._lock.release()

        return (),()

    def _begin(self, *ignored):
        from thread import get_ident
        self._tlock.acquire()
        self._tthread = get_ident()
Kevin Deldycke's avatar
Kevin Deldycke committed
122

Jean-Paul Smets's avatar
Jean-Paul Smets committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    def _finish(self, *ignored):
        from thread import get_ident
        if not self._tlock.locked() or self._tthread != get_ident():
            LOG('ZMySQLDA', INFO, "ignoring _finish")
            return
        # BEGIN commit
        LOG('ZMySQLDDA', INFO, "BEGIN commit")
        try:
            if self._transactions:
                self.db.query("BEGIN")
                self.db.store_result()
            if self._mysql_lock:
                self.db.query("SELECT GET_LOCK('%s',0)" % self._mysql_lock)
                self.db.store_result()
        except:
            LOG('ZMySQLDDA', ERROR, "exception during _begin",
                error=sys.exc_info())
            self._tlock.release()
            raise
Kevin Deldycke's avatar
Kevin Deldycke committed
142
        # Execute SQL
Jean-Paul Smets's avatar
Jean-Paul Smets committed
143 144 145 146
        db = self.db
        for qs in self.sql_string_list:
            try:
                db.query(qs)
Kevin Deldycke's avatar
Kevin Deldycke committed
147
                c=db.store_result()
Jean-Paul Smets's avatar
Jean-Paul Smets committed
148 149 150 151 152 153 154 155
            except OperationalError, m:
                if m[0] not in hosed_connection: raise
                # Hm. maybe the db is hosed.  Let's restart it.
                db=self.db=apply(self.Database_Connection, (), self.kwargs)
                try:
                    db.query(qs)
                    c=db.store_result()
                except OperationalError, m:
Kevin Deldycke's avatar
Kevin Deldycke committed
156
                    raise
Jean-Paul Smets's avatar
Jean-Paul Smets committed
157
            LOG('ZMySQLDDA', INFO, "Execute %s" % qs)
Kevin Deldycke's avatar
Kevin Deldycke committed
158
        # Finish commit
Jean-Paul Smets's avatar
Jean-Paul Smets committed
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
        LOG('ZMySQLDDA', INFO, "FINISH commit")
        try:
            try:
                if self._mysql_lock:
                    self.db.query("SELECT RELEASE_LOCK('%s')" % self._mysql_lock)
                    self.db.store_result()
                if self._transactions:
                    self.db.query("COMMIT")
                self.db.store_result()
            except:
                LOG('ZMySQLDDA', ERROR, "exception during _finish",
                    error=sys.exc_info())
                raise
        finally:
            self._tlock.release()

    def _abort(self, *ignored):
        from thread import get_ident
        if not self._tlock.locked() or self._tthread != get_ident():
            LOG('ZMySQLDDA', INFO, "ignoring _abort")
            return
Kevin Deldycke's avatar
Kevin Deldycke committed
180
        self._tlock.release()