source: indico/indico/MaKaC/common/db.py @ 9651ae

burotelhello-world-walkthroughipv6new-webexv0.97-seriesv0.98-seriesv0.98.2v0.98.3v0.98b1v0.98b2v0.99v1.0v1.1
Last change on this file since 9651ae was 9651ae, checked in by Pedro Ferreira <jose.pedro.ferreira@…>, 3 years ago

[FIX] isConnected bug

  • Error reports couldn't be sent because of it;
  • Property mode set to 100644
File size: 6.8 KB
Line 
1# -*- coding: utf-8 -*-
2##
3##
4## This file is part of CDS Indico.
5## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
6##
7## CDS Indico is free software; you can redistribute it and/or
8## modify it under the terms of the GNU General Public License as
9## published by the Free Software Foundation; either version 2 of the
10## License, or (at your option) any later version.
11##
12## CDS Indico is distributed in the hope that it will be useful, but
13## WITHOUT ANY WARRANTY; without even the implied warranty of
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15## General Public License for more details.
16##
17## You should have received a copy of the GNU General Public License
18## along with CDS Indico; if not, write to the Free Software Foundation, Inc.,
19## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20
21"""This file contains the implementation of some classes dealing with the DB
22    so it's usage is easier and more transparent to the rest of the application
23"""
24import os
25import sys
26import threading
27import pkg_resources
28
29from ZEO.ClientStorage import ClientStorage
30from ZODB.DB import DB
31import transaction
32import ZODB
33
34from MaKaC.consoleScripts.installBase import getIndicoInstallMode
35skip_imports = getIndicoInstallMode()
36
37if not skip_imports:
38    from MaKaC.common.logger import Logger
39    from MaKaC.i18n import _
40
41class MaKaCDB(DB):
42    """Subclass of ZODB.DB necessary to remove possible existing dependencies
43        from IC"""
44
45    def classFactory(self, connection, modulename, globalname):
46        if globalname=="PersistentMapping":
47            modulename="persistent.mapping"
48        elif globalname=="PersistentList":
49            modulename="persistent.list"
50        elif modulename.startswith("IndexedCatalog.BTrees."):
51            modulename="BTrees.%s"%modulename[22:]
52        return DB.classFactory(self, connection, modulename, globalname)
53
54
55
56class DBMgr:
57    """This class provides the access point to the Shelf (every client will
58        use this class in order to obtain a shelf) and some mechanism to
59        ensure there is only one connection opened to the DB during a single
60        request.
61        This class must not be instantiated, an instance can be obtained
62        though the "getInstance" method (implements the singleton pattern
63        to ensure unicity)
64        Needs to be checked if the class (static) attribute _instance is
65        thread-safe: as it is shared by all the objects of this class,
66        it could provoke concurrency troubles having 2 threads using the db
67        connection at the same time. However, the model under which we are
68        programming is not multi-threaded (mod_python seems to run different
69        interpreters for each apache subprocess, see mod_python doc section
70        4.1) so this thechnique can be used. This has to be taken into account
71        when migrating the system to a multi-threading environment.
72    """
73    _instance = None
74
75    def __init__( self, hostname=None, port=None ):
76        import Configuration # Please leave this import here, db.py is imported during installation process
77        cfg = Configuration.Config.getInstance()
78
79        if not hostname:
80            hostname = cfg.getDBConnectionParams()[0]
81        if not port:
82            port = cfg.getDBConnectionParams()[1]
83
84        self._storage=ClientStorage((hostname, port), username=cfg.getDBUserName(), password=cfg.getDBPassword(), realm=cfg.getDBRealm())
85        self._db=MaKaCDB(self._storage)
86        self._conn={}
87
88    @classmethod
89    def getInstance( cls, *args, **kwargs ):
90        if cls._instance == None:
91            Logger.get('dbmgr').debug('cls._instance is None')
92            cls._instance=DBMgr(*args, **kwargs)
93        return cls._instance
94
95    @staticmethod
96    def _getUniqueIdentifier():
97        return threading._get_ident()
98
99    def _getConnObject(self):
100        tid = DBMgr._getUniqueIdentifier()
101        return self._conn[tid]
102
103    def _delConnObject(self):
104        tid = DBMgr._getUniqueIdentifier()
105        del self._conn[tid]
106
107    def startRequest( self ):
108        """Initialise the DB and starts a new transaction.
109        """
110
111        tid = DBMgr._getUniqueIdentifier()
112
113        self._conn[tid] = self._db.open()
114        Logger.get('dbmgr').debug('Allocated connection for %s - table size is %s' % \
115                                  (tid, len(self._conn)))
116
117    def endRequest( self, commit=True ):
118        """Closes the DB and commits changes.
119        """
120        if commit:
121            self.commit()
122        else:
123            self.abort()
124
125        #modification vendredi 010907
126#        try:
127#            self._conn.close()
128#            self._conn=None
129#        except:
130#            pass
131
132        self._getConnObject().close()
133        self._delConnObject()
134
135    def getDBConnection( self ):
136        return self._getConnObject()
137
138    def isConnected( self ):
139        tid = DBMgr._getUniqueIdentifier()
140
141        return tid in self._conn
142
143    def getDBConnCache(self):
144        conn = self._getConnObject()
145        return conn._cache
146
147    def getDBClassFactory(self):
148        return self._db.classFactory
149
150    def commit(self, sub=False):
151        if (sub):
152            transaction.savepoint()
153        else:
154            transaction.commit()
155
156    def commitZODBOld(self, sub=False):
157            transaction.commit(sub)
158
159    def abort(self):
160        transaction.abort()
161
162    def sync(self):
163        self._getConnObject().sync()
164
165    def pack( self, days=1 ):
166        self._storage.pack(days=days)
167
168    def undoInfo(self, stepNumber=0):
169        # One step is made of 1000 transactions. First step is 0 and returns
170        # transactions 0 to 999.
171        return self._db.undoInfo(stepNumber*1000, (stepNumber+1)*1000)
172
173    def undo(self, trans_id):
174        self._db.undo(trans_id)
175
176    def getDBSize( self ):
177        """Return an approximate size of the database, in bytes."""
178        return self._storage.getSize()
179
180    def loadObject(self, oid, version):
181        return self._storage.load(oid, version)
182
183    def storeObject(self, oid, serial, data, version, trans):
184        return self._storage.store(oid, serial, data, version, trans)
185
186    def tpcBegin(self, trans):
187        self._storage.tpc_begin(trans)
188
189    def tpcVote(self, trans):
190        self._storage.tpc_vote(trans)
191
192    def tpcFinish(self, trans):
193        self._storage.tpc_finish(trans)
194
195    # ZODB version check
196    try:
197        zodbPkg = pkg_resources.require('ZODB3')[0]
198        zodbVersion = zodbPkg.parsed_version
199        zodbVersion = (int(zodbVersion[0]), int(zodbVersion[1]))
200    except pkg_resources.DistributionNotFound:
201        # Very old versions, in which ZODB didn't register
202        # with pkg_resources
203        import ZODB
204        zodbVersion = ZODB.__version__.split('.')
205
206    if int(zodbVersion[0]) < 3:
207        raise Exception("ZODB 3 required! %s found" % zodbPkg.version)
208    elif int(zodbVersion[1]) < 7:
209        commit = commitZODBOld
210
211
Note: See TracBrowser for help on using the repository browser.