| [9033fd] | 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 | |
|---|
| [136ed9a] | 21 | import threading |
|---|
| 22 | from contextlib import contextmanager |
|---|
| 23 | |
|---|
| [9033fd] | 24 | from MaKaC.common import Configuration |
|---|
| 25 | from MaKaC.common.db import DBMgr |
|---|
| 26 | from MaKaC.rb_dalManager import DALManagerBase |
|---|
| 27 | from MaKaC.errors import MaKaCError |
|---|
| 28 | from MaKaC.common import db, info |
|---|
| 29 | from BTrees.IOBTree import IOBTree |
|---|
| 30 | from BTrees.OOBTree import OOBTree |
|---|
| 31 | |
|---|
| 32 | from ZEO import ClientStorage |
|---|
| 33 | from ZODB.DB import DB |
|---|
| 34 | import transaction |
|---|
| 35 | |
|---|
| 36 | |
|---|
| [136ed9a] | 37 | @contextmanager |
|---|
| 38 | def dummyContextManager(): |
|---|
| 39 | yield |
|---|
| 40 | |
|---|
| 41 | |
|---|
| 42 | class DummyConnection(): |
|---|
| 43 | """ |
|---|
| 44 | Used so that we can use context managers for database connections |
|---|
| 45 | without producing failures when RB is not active. |
|---|
| 46 | Of course tis is not the ideal solution, but it's the best possible |
|---|
| 47 | without changing the whole RB DB code. |
|---|
| 48 | """ |
|---|
| 49 | def transaction(self): |
|---|
| 50 | return dummyContextManager() |
|---|
| 51 | |
|---|
| 52 | |
|---|
| [336214] | 53 | class DBConnection: |
|---|
| 54 | |
|---|
| 55 | def __init__(self, minfo): |
|---|
| 56 | self.connection = None |
|---|
| 57 | self.root = None |
|---|
| 58 | |
|---|
| 59 | self.storage = ClientStorage.ClientStorage( |
|---|
| 60 | minfo.getRoomBookingDBConnectionParams(), |
|---|
| 61 | username=minfo.getRoomBookingDBUserName(), |
|---|
| 62 | password=minfo.getRoomBookingDBPassword(), |
|---|
| 63 | realm=minfo.getRoomBookingDBRealm()) |
|---|
| 64 | self.db = DB(self.storage) |
|---|
| 65 | |
|---|
| 66 | def connect(self): |
|---|
| 67 | if not self.isConnected(): |
|---|
| 68 | if DALManager.usesMainIndicoDB(): |
|---|
| 69 | self.connection = DBMgr.getInstance().getDBConnection() |
|---|
| 70 | else: |
|---|
| 71 | self.connection = self.db.open() |
|---|
| 72 | self.root = self.connection.root() |
|---|
| 73 | |
|---|
| 74 | def isConnected(self): |
|---|
| 75 | if not self.connection: |
|---|
| 76 | return False |
|---|
| 77 | return True |
|---|
| 78 | |
|---|
| 79 | def getRoot(self, name=""): |
|---|
| 80 | if name == "": |
|---|
| 81 | return self.root |
|---|
| 82 | elif self.root != None: |
|---|
| 83 | if name in self.root.keys() and self.root[name]: |
|---|
| 84 | return self.root[name] |
|---|
| 85 | else: |
|---|
| 86 | # create the branch |
|---|
| 87 | if name in ["Rooms", "Reservations"]: |
|---|
| 88 | self.root[name] = IOBTree() |
|---|
| 89 | elif name in ["RoomReservationsIndex", "UserReservationsIndex", |
|---|
| 90 | "DayReservationsIndex"]: |
|---|
| 91 | self.root[name] = OOBTree() |
|---|
| 92 | elif name in ["EquipmentList", "CustomAttributesList"]: |
|---|
| 93 | self.root[name] = {} |
|---|
| 94 | else: |
|---|
| 95 | return None |
|---|
| 96 | return self.root[name] |
|---|
| 97 | else: |
|---|
| 98 | raise MaKaCError("Cannot connect to the room booking database") |
|---|
| 99 | |
|---|
| 100 | def disconnect(self): |
|---|
| 101 | if DALManager.usesMainIndicoDB(): |
|---|
| 102 | return |
|---|
| 103 | if self.isConnected(): |
|---|
| 104 | self.connection.close() |
|---|
| 105 | self.root = None |
|---|
| 106 | self.connection = None |
|---|
| 107 | |
|---|
| 108 | def commit(self): |
|---|
| 109 | if DALManager.usesMainIndicoDB(): |
|---|
| 110 | return |
|---|
| 111 | if self.isConnected(): |
|---|
| 112 | self.connection.transaction_manager.get().commit() |
|---|
| 113 | |
|---|
| 114 | def rollback(self): |
|---|
| 115 | if DALManager.usesMainIndicoDB(): |
|---|
| 116 | return |
|---|
| 117 | if self.isConnected(): |
|---|
| 118 | self.connection.transaction_manager.get().abort() |
|---|
| 119 | |
|---|
| 120 | def sync(self): |
|---|
| 121 | if DALManager.usesMainIndicoDB(): |
|---|
| 122 | return |
|---|
| 123 | if self.isConnected(): |
|---|
| 124 | self.connection.sync() |
|---|
| 125 | |
|---|
| 126 | def pack(self, days=1): |
|---|
| 127 | if DALManager.usesMainIndicoDB(): |
|---|
| 128 | return |
|---|
| 129 | self.db.pack(days=days) |
|---|
| 130 | |
|---|
| [136ed9a] | 131 | def transaction(self): |
|---|
| 132 | """ |
|---|
| 133 | Calls the ZODB context manager for the connection |
|---|
| 134 | """ |
|---|
| 135 | return self.db.transaction() |
|---|
| 136 | |
|---|
| [336214] | 137 | |
|---|
| 138 | class DALManager(DALManagerBase): |
|---|
| [9033fd] | 139 | """ ZODB specific implementation. """ |
|---|
| 140 | |
|---|
| [136ed9a] | 141 | _instances = {} |
|---|
| [9033fd] | 142 | |
|---|
| 143 | @staticmethod |
|---|
| 144 | def usesMainIndicoDB(): |
|---|
| 145 | cfg = Configuration.Config.getInstance() |
|---|
| 146 | minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance() |
|---|
| 147 | if cfg.getDBConnectionParams() == minfo.getRoomBookingDBConnectionParams(): |
|---|
| 148 | return True |
|---|
| 149 | else: |
|---|
| 150 | return False |
|---|
| [06b07f] | 151 | |
|---|
| [9033fd] | 152 | @staticmethod |
|---|
| [136ed9a] | 153 | def getInstance(create=True): |
|---|
| 154 | tid = threading._get_ident() |
|---|
| 155 | instance = DALManager._instances.get(tid) |
|---|
| 156 | |
|---|
| 157 | if not instance and create: |
|---|
| [9033fd] | 158 | minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance() |
|---|
| [136ed9a] | 159 | instance = DBConnection(minfo) |
|---|
| 160 | DALManager._instances[tid] = instance |
|---|
| 161 | return instance |
|---|
| [9033fd] | 162 | |
|---|
| 163 | @staticmethod |
|---|
| 164 | def isConnected(): |
|---|
| 165 | """ |
|---|
| 166 | Returns true if the current DALManager is connected |
|---|
| 167 | """ |
|---|
| [136ed9a] | 168 | if DALManager.getInstance(create=False): |
|---|
| 169 | return DALManager.getInstance().isConnected() |
|---|
| 170 | else: |
|---|
| 171 | return False |
|---|
| [9033fd] | 172 | |
|---|
| 173 | @staticmethod |
|---|
| 174 | def getRoot(name=""): |
|---|
| [136ed9a] | 175 | return DALManager.getInstance().getRoot(name) |
|---|
| [06b07f] | 176 | |
|---|
| [9033fd] | 177 | @staticmethod |
|---|
| 178 | def connect(): |
|---|
| [336214] | 179 | DALManager.getInstance().connect() |
|---|
| [06b07f] | 180 | |
|---|
| [9033fd] | 181 | @staticmethod |
|---|
| 182 | def disconnect(): |
|---|
| [136ed9a] | 183 | DALManager.getInstance().disconnect() |
|---|
| [06b07f] | 184 | |
|---|
| [9033fd] | 185 | @staticmethod |
|---|
| 186 | def commit(): |
|---|
| [136ed9a] | 187 | DALManager.getInstance().commit() |
|---|
| [06b07f] | 188 | |
|---|
| [9033fd] | 189 | @staticmethod |
|---|
| 190 | def rollback(): |
|---|
| [136ed9a] | 191 | DALManager.getInstance().rollback() |
|---|
| [9033fd] | 192 | |
|---|
| 193 | @staticmethod |
|---|
| 194 | def sync(): |
|---|
| [136ed9a] | 195 | DALManager.getInstance().sync() |
|---|
| [9033fd] | 196 | |
|---|
| 197 | @staticmethod |
|---|
| [336214] | 198 | def pack(days=1): |
|---|
| [136ed9a] | 199 | DALManager.getInstance().pack() |
|---|
| 200 | |
|---|
| 201 | @staticmethod |
|---|
| 202 | def dummyConnection(): |
|---|
| 203 | return DummyConnection() |
|---|