Exemple #1
0
    def __copy_transaction(self, other, trans):
        # Originally adapted from ZODB.blob.BlobStorageMixin
        tpc = self.tpc
        num_txn_records = 0
        txn_data_size = 0
        num_blobs = 0
        tmp_blobs_to_rm = []

        tpc.tpc_begin(trans, trans.tid, trans.status)
        for record in trans:
            num_txn_records += 1
            if record.data:
                txn_data_size += len(record.data)

            blobfile = None
            if is_blob_record(record.data):
                try:
                    blobfile = other.openCommittedBlobFile(
                        record.oid, record.tid)
                except POSKeyError:
                    logger.exception("Failed to open blob to copy")
            if blobfile is not None:
                fd, name = tempfile.mkstemp(
                    suffix='.tmp', dir=self.blobhelper.temporaryDirectory())
                tmp_blobs_to_rm.append(name)
                logger.log(TRACE,
                           "Copying %s to temporary blob file %s for upload",
                           blobfile, name)

                with os.fdopen(fd, 'wb') as target:
                    # If we don't get the length, ``copy_blob`` will.
                    old_pos = blobfile.tell()
                    blobfile.seek(0, 2)
                    length = blobfile.tell()
                    blobfile.seek(old_pos)

                    copy_blob(blobfile, target, length)
                    txn_data_size += length
                blobfile.close()
                self.restore.restoreBlob(record.oid, record.tid, record.data,
                                         name, record.data_txn, trans)
            else:
                self.restore.restore(record.oid, record.tid, record.data, '',
                                     record.data_txn, trans)

        tpc.tpc_vote(trans)
        tpc.tpc_finish(trans)

        num_blobs = len(tmp_blobs_to_rm)
        if num_blobs:
            for tmp_blob in tmp_blobs_to_rm:
                logger.log(TRACE, "Removing temporary blob file %s", tmp_blob)
                try:
                    os.unlink(tmp_blob)
                except OSError:
                    pass

        return num_txn_records, txn_data_size, num_blobs
Exemple #2
0
    def restore_one(self, active_txn_meta,
                    oid, tid, data):

        # The signature for both ``restore`` and ``restoreBlob``
        # is:
        #
        #   (oid, serial, data, (blobfilename|prev_txn), version, txn)
        #
        # Where ``txn`` is the TransactionMetaData object
        # originally passed to ``tpc_begin``. It is only used to
        # check that the same object has been passed.
        #
        # ``prev_txn`` is not used but would come from ``record.data_txn``

        txn_data_size = len(data) if data else 0

        blobfile = None
        if is_blob_record(data):
            try:
                blobfile = self.storage.openCommittedBlobFile(
                    oid, tid)
            except POSKeyError: # pragma: no cover
                logger.exception("Failed to open blob to copy")

        # We may not be able to read the data after this.
        data = self.restore._crs_transform_record_data(data)
        if blobfile is not None:
            fd, name = tempfile.mkstemp(
                suffix='.tmp',
                dir=self.blobhelper.temporaryDirectory()
            )
            self.temp_blobs_to_rm.append(name)
            logger.log(
                TRACE,
                "Copying %s to temporary blob file %s for upload",
                blobfile, name)

            with os.fdopen(fd, 'wb') as target:
                # If we don't get the length, ``copy_blob`` will.
                old_pos = blobfile.tell()
                blobfile.seek(0, 2)
                length = blobfile.tell()
                blobfile.seek(old_pos)

                copy_blob(blobfile, target, length)
                txn_data_size += length
            blobfile.close()
            self.restore.restoreBlob(oid, tid, data,
                                     name, None, active_txn_meta)
        else:
            self.restore.restore(oid, tid, data,
                                 '', None, active_txn_meta)

        return txn_data_size, blobfile is not None
Exemple #3
0
    def copyTransactionsFrom(self, other):
        # pylint:disable=too-many-locals
        # adapted from ZODB.blob.BlobStorageMixin
        begin_time = time.time()
        txnum = 0
        total_size = 0
        blobhelper = self.blobhelper
        tpc = self.tpc
        restore = self.restore

        logger.info("Counting the transactions to copy.")
        num_txns = 0
        for _ in other.iterator():
            num_txns += 1
        logger.info("Copying %d transactions", num_txns)

        for trans in other.iterator():
            txnum += 1
            num_txn_records = 0

            tpc.tpc_begin(trans, trans.tid, trans.status)
            for record in trans:
                blobfile = None
                if is_blob_record(record.data):
                    try:
                        blobfile = other.openCommittedBlobFile(
                            record.oid, record.tid)
                    except POSKeyError:
                        pass
                if blobfile is not None:
                    fd, name = tempfile.mkstemp(
                        suffix='.tmp', dir=blobhelper.temporaryDirectory())
                    os.close(fd)
                    with open(name, 'wb') as target:
                        copy_blob(blobfile, target)
                    blobfile.close()
                    restore.restoreBlob(record.oid, record.tid, record.data,
                                        name, record.data_txn, trans)
                else:
                    restore.restore(record.oid, record.tid, record.data, '',
                                    record.data_txn, trans)
                num_txn_records += 1
                if record.data:
                    total_size += len(record.data)
            tpc.tpc_vote(trans)
            tpc.tpc_finish(trans)

            pct_complete = '%1.2f%%' % (txnum * 100.0 / num_txns)
            elapsed = time.time() - begin_time
            if elapsed:
                rate = total_size / 1e6 / elapsed
            else:
                rate = 0.0
            rate_str = '%1.3f' % rate
            logger.info("Copied tid %d,%5d records | %6s MB/s (%6d/%6d,%7s)",
                        bytes8_to_int64(trans.tid), num_txn_records, rate_str,
                        txnum, num_txns, pct_complete)

        elapsed = time.time() - begin_time
        logger.info(
            "All %d transactions copied successfully in %4.1f minutes.", txnum,
            elapsed / 60.0)
Exemple #4
0
    def copyTransactionsFrom(self, other):
        # pylint:disable=too-many-locals,too-many-statements,too-many-branches
        # adapted from ZODB.blob.BlobStorageMixin
        begin_time = time.time()
        log_at = begin_time + self.log_interval
        txnum = 0
        total_size = 0
        blobhelper = self.blobhelper
        tpc = self.tpc
        restore = self.restore

        logger.info("Counting the transactions to copy.")
        other_it = other.iterator()
        logger.debug("Opened the other iterator: %s", other_it)
        try:
            num_txns = len(other_it)
            if num_txns == 0:
                # Hmm, that shouldn't really be right, should it?
                # Try the other path.
                raise TypeError()
        except TypeError:
            logger.debug("Iterator %s doesn't support len()", other_it)
            num_txns = 0
            for _ in other_it:
                num_txns += 1
            other_it.close()
            other_it = other.iterator()
        logger.info("Copying %d transactions", num_txns)

        tmp_blobs_to_rm = []
        for trans in other_it:
            txnum += 1
            num_txn_records = 0

            tpc.tpc_begin(trans, trans.tid, trans.status)
            for record in trans:
                blobfile = None
                if is_blob_record(record.data):
                    try:
                        blobfile = other.openCommittedBlobFile(
                            record.oid, record.tid)
                    except POSKeyError:
                        pass
                if blobfile is not None:
                    fd, name = tempfile.mkstemp(
                        suffix='.tmp', dir=blobhelper.temporaryDirectory())
                    tmp_blobs_to_rm.append(name)
                    logger.debug(
                        "Copying %s to temporary blob file %s for upload",
                        blobfile, name)

                    with os.fdopen(fd, 'wb') as target:
                        copy_blob(blobfile, target)
                    blobfile.close()
                    restore.restoreBlob(record.oid, record.tid, record.data,
                                        name, record.data_txn, trans)
                else:
                    restore.restore(record.oid, record.tid, record.data, '',
                                    record.data_txn, trans)
                num_txn_records += 1
                if record.data:
                    total_size += len(record.data)
            tpc.tpc_vote(trans)
            tpc.tpc_finish(trans)

            for tmp_blob in tmp_blobs_to_rm:
                logger.debug("Removing temporary blob file %s", tmp_blob)
                try:
                    os.unlink(tmp_blob)
                except OSError:
                    pass
            del tmp_blobs_to_rm[:]

            if txnum % self.log_count == 0 and time.time() > log_at:
                now = time.time()
                log_at = now + self.log_interval

                pct_complete = '%1.2f%%' % (txnum * 100.0 / num_txns)
                elapsed = now - begin_time
                if elapsed:
                    rate = total_size / 1e6 / elapsed
                else:
                    rate = 0.0
                rate_str = '%1.3f' % rate

                logger.info(
                    "Copied tid %d,%5d records | %6s MB/s (%6d/%6d,%7s)",
                    bytes8_to_int64(trans.tid), num_txn_records, rate_str,
                    txnum, num_txns, pct_complete)

        elapsed = time.time() - begin_time
        logger.info(
            "All %d transactions copied successfully in %4.1f minutes.", txnum,
            elapsed / 60.0)