Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
 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)]
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
 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')
Ejemplo n.º 5
0
 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
Ejemplo n.º 6
0
 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
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
0
 def readOnlyAccess(self, conn, message):
     raise ReadOnlyError(message)
Ejemplo n.º 9
0
 def tpc_begin(self, transaction, begin_factory):
     if self.read_only:
         raise ReadOnlyError()
     return super(NotInTransaction, self).tpc_begin(transaction,
                                                    begin_factory)
Ejemplo n.º 10
0
 def store(self, *_args, **_kwargs):
     if self.read_only:
         raise ReadOnlyError()
     self._no_transaction()
Ejemplo n.º 11
0
    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()