def register(self, storage_id, read_only): """Select the storage that this client will use This method must be the first one called by the client. For authenticated storages this method will be called by the client immediately after authentication is finished. """ if self.auth_realm and not self.authenticated: raise AuthError("Client was never authenticated with server!") if self.storage is not None: self.log("duplicate register() call") raise ValueError("duplicate register() call") storage = self.server.storages.get(storage_id) if storage is None: self.log("unknown storage_id: %s" % storage_id) raise ValueError("unknown storage: %s" % storage_id) if not read_only and (self.read_only or storage.isReadOnly()): raise ReadOnlyError() self.read_only = self.read_only or read_only self.storage_id = storage_id self.storage = storage self.setup_delegation() self.timeout, self.stats = self.server.register_connection( storage_id, self)
def new_oids(self, n=100): """Return a sequence of n new oids, where n defaults to 100""" if self.read_only: raise ReadOnlyError() if n <= 0: n = 1 return [self.storage.new_oid() for i in range(n)]
def tpc_begin(self, id, user, description, ext, tid=None, status=" "): if self.read_only: raise ReadOnlyError() if self.transaction is not None: if self.transaction.id == id: self.log("duplicate tpc_begin(%s)" % repr(id)) return else: raise StorageTransactionError("Multiple simultaneous tpc_begin" " requests from one client.") t = TransactionMetaData(user, description, ext) t.id = id self.serials = [] self.conflicts = {} self.invalidated = [] self.txnlog = CommitLog() self.blob_log = [] self.tid = tid self.status = status self.stats.active_txns += 1 # Assign the transaction attribute last. This is so we don't # think we've entered TPC until everything is set. Why? # Because if we have an error after this, the server will # think it is in TPC and the client will think it isn't. At # that point, the client will keep trying to enter TPC and # server won't let it. Errors *after* the tpc_begin call will # cause the client to abort the transaction. # (Also see https://bugs.launchpad.net/zodb/+bug/374737.) self.transaction = t
def test_readonly_error(self): from ZODB.POSException import ReadOnlyError response = self.call_fut(ReadOnlyError()) self.assertEqual(response['error_message'], 'Site is in Read Only Mode') response = self.call_fut(ReadOnlyError) self.assertEqual(response['error_message'], 'Site is in Read Only Mode')
def tpc_begin(self, storage, transaction): # XXX: Signature needs to change. if self.read_only: raise ReadOnlyError() if transaction is self.transaction: # Also handles None. raise StorageTransactionError("Duplicate tpc_begin calls for same transaction.") state = SharedTPCState(self, storage, transaction) try: return self.begin_factory(state) except: state.abort() raise
def _check_tid(self, tid, exc=None): if self.read_only: raise ReadOnlyError() if self.transaction is None: caller = sys._getframe().f_back.f_code.co_name self.log("no current transaction: %s()" % caller, level=logging.WARNING) if exc is not None: raise exc(None, tid) else: return 0 if self.transaction.id != tid: caller = sys._getframe().f_back.f_code.co_name self.log("%s(%s) invalid; current transaction = %s" % (caller, repr(tid), repr(self.transaction.id)), logging.WARNING) if exc is not None: raise exc(self.transaction.id, tid) else: return 0 return 1
def tpc_begin(self, id, user, description, ext, tid=None, status=" "): if self.read_only: raise ReadOnlyError() if self.transaction is not None: if self.transaction.id == id: self.log("duplicate tpc_begin(%s)" % repr(id)) return else: raise StorageTransactionError("Multiple simultaneous tpc_begin" " requests from one client.") self.transaction = t = transaction.Transaction() t.id = id t.user = user t.description = description t._extension = ext self.serials = [] self.invalidated = [] self.txnlog = CommitLog() self.tid = tid self.status = status self.store_failed = 0 self.stats.active_txns += 1
def readOnlyAccess(self, conn, message): raise ReadOnlyError(message)
def tpc_begin(self, transaction, begin_factory): if self.read_only: raise ReadOnlyError() return super(NotInTransaction, self).tpc_begin(transaction, begin_factory)
def store(self, *_args, **_kwargs): if self.read_only: raise ReadOnlyError() self._no_transaction()
def pack(self, t, referencesf, prepack_only=False, skip_prepack=False, sleep=None): """Pack the storage. Holds the pack lock for the duration.""" # pylint:disable=too-many-branches if self._is_read_only: raise ReadOnlyError() prepack_only = prepack_only or self._options.pack_prepack_only skip_prepack = skip_prepack or self._options.pack_skip_prepack if prepack_only and skip_prepack: raise ValueError('Pick either prepack_only or skip_prepack.') def get_references(state): """Return an iterable of the set of OIDs the given state refers to.""" if not state: return () assert isinstance(state, bytes), type(state) # XXX PY3: str(state) return {u64(oid) for oid in referencesf(state)} # Use a private connection (lock_conn and lock_cursor) to # hold the pack lock. Have the adapter open temporary # connections to do the actual work, allowing the adapter # to use special transaction modes for packing. adapter = self._adapter if not skip_prepack: # Find the latest commit before or at the pack time. pack_point = repr(TimeStamp(*time.gmtime(t)[:5] + (t % 60, ))) tid_int = adapter.packundo.choose_pack_transaction(u64(pack_point)) if tid_int is None: log.debug( "all transactions before %s have already " "been packed", time.ctime(t)) return if prepack_only: log.info("pack: beginning pre-pack") s = time.ctime(TimeStamp(p64(tid_int)).timeTime()) log.info("pack: analyzing transactions committed " "%s or before", s) # In pre_pack, the adapter fills tables with # information about what to pack. The adapter # must not actually pack anything yet. adapter.packundo.pre_pack(tid_int, get_references) else: # Need to determine the tid_int from the pack_object table tid_int = adapter.packundo._find_pack_tid() if prepack_only: log.info("pack: pre-pack complete") else: # Now pack. if self.blobhelper is not None: packed_func = self.blobhelper.after_pack else: packed_func = None adapter.packundo.pack(tid_int, sleep=sleep, packed_func=packed_func) self.sync() self._pack_finished()