193 lines
7.7 KiB
Python
193 lines
7.7 KiB
Python
|
|
"""
|
||
|
|
WorkerPoolMixin - Mixin für Worker-Pool-Verwaltung.
|
||
|
|
|
||
|
|
Dieses Mixin enthält alle Methoden zur Verwaltung der Saxon- und FOP-Worker-Pools
|
||
|
|
für das MainWindow.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import logging
|
||
|
|
|
||
|
|
from PySide6.QtWidgets import QMessageBox
|
||
|
|
|
||
|
|
from conf import app_settings, XsltVersion
|
||
|
|
from transform import TransformationJob, set_saxon_worker_pool
|
||
|
|
from saxon_pool import SaxonWorkerPool
|
||
|
|
from saxon_pool_s9api import SaxonWorkerPoolS9Api
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
class WorkerPoolMixin:
|
||
|
|
"""
|
||
|
|
Mixin für Worker-Pool-Verwaltung.
|
||
|
|
|
||
|
|
Dieses Mixin wird von MainWindow verwendet und erwartet folgende Attribute:
|
||
|
|
- self.project: Das aktuelle Projekt
|
||
|
|
"""
|
||
|
|
|
||
|
|
def _initialize_saxon_worker_pool(self):
|
||
|
|
"""Initialisiert den Saxon-Worker-Pool für schnelle Transformationen."""
|
||
|
|
try:
|
||
|
|
# Shutdown vorherigen Pool falls vorhanden
|
||
|
|
self._shutdown_saxon_worker_pool()
|
||
|
|
|
||
|
|
# Prüfe ob SaxonWorkerPool aktiviert ist
|
||
|
|
if not app_settings.use_saxon_worker_pool:
|
||
|
|
logger.info("SaxonWorkerPool deaktiviert - Verwende Fallback-Modus (subprocess)")
|
||
|
|
return
|
||
|
|
|
||
|
|
if not self.project:
|
||
|
|
logger.warning("Kein Projekt geladen, Saxon-Worker-Pool nicht initialisiert")
|
||
|
|
return
|
||
|
|
|
||
|
|
# Hole Tool-Konfigurationen
|
||
|
|
java_vm = next((vm for vm in app_settings.java_vms if vm.id == self.project.java_vm_id), None)
|
||
|
|
saxon_jar = next((jar for jar in app_settings.saxon_jars if jar.id == self.project.saxon_jar_id), None)
|
||
|
|
|
||
|
|
if not java_vm or not saxon_jar:
|
||
|
|
logger.warning("Java VM oder Saxon JAR nicht gefunden, Pool nicht initialisiert")
|
||
|
|
return
|
||
|
|
|
||
|
|
# Erstelle Worker-Pool (wähle richtige Variante basierend auf XSLT-Version)
|
||
|
|
num_workers = app_settings.max_workers
|
||
|
|
log_dir = self.project.project_dir / "temp"
|
||
|
|
|
||
|
|
# Wähle die richtige Worker-Pool-Implementierung
|
||
|
|
if app_settings.saxon_xslt_version == XsltVersion.XSLT_1_0:
|
||
|
|
# JAXP-basierte Variante für XSLT 1.0
|
||
|
|
pool = SaxonWorkerPool(
|
||
|
|
num_workers=num_workers,
|
||
|
|
java_vm_path=java_vm.path_to_binary_file,
|
||
|
|
saxon_jar_path=saxon_jar.path_to_jar_file,
|
||
|
|
classpath_cache=TransformationJob._classpath_cache,
|
||
|
|
log_dir=log_dir,
|
||
|
|
)
|
||
|
|
pool_type = "JAXP (XSLT 1.0)"
|
||
|
|
else:
|
||
|
|
# s9api-basierte Variante für XSLT 2.0/3.0
|
||
|
|
pool = SaxonWorkerPoolS9Api(
|
||
|
|
num_workers=num_workers,
|
||
|
|
java_vm_path=java_vm.path_to_binary_file,
|
||
|
|
saxon_jar_path=saxon_jar.path_to_jar_file,
|
||
|
|
classpath_cache=TransformationJob._classpath_cache,
|
||
|
|
log_dir=log_dir,
|
||
|
|
)
|
||
|
|
pool_type = "s9api (XSLT 2.0/3.0)"
|
||
|
|
|
||
|
|
# Setze globalen Pool
|
||
|
|
set_saxon_worker_pool(pool)
|
||
|
|
|
||
|
|
logger.info(
|
||
|
|
f"Saxon-Worker-Pool initialisiert: {num_workers} Worker mit {pool_type} "
|
||
|
|
f"(erwartet: {num_workers}x schneller für Saxon-Transformationen)"
|
||
|
|
)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Fehler beim Initialisieren des Saxon-Worker-Pools: {e}")
|
||
|
|
logger.info("Fallback auf subprocess-Modus")
|
||
|
|
# Kein Pool ist OK - Fallback auf subprocess
|
||
|
|
|
||
|
|
def _shutdown_saxon_worker_pool(self):
|
||
|
|
"""Beendet den Saxon-Worker-Pool sauber."""
|
||
|
|
try:
|
||
|
|
# Importiere transform um Zugriff auf globalen Pool zu haben
|
||
|
|
import transform
|
||
|
|
|
||
|
|
if transform._saxon_worker_pool:
|
||
|
|
logger.info("Beende Saxon-Worker-Pool...")
|
||
|
|
transform._saxon_worker_pool.shutdown()
|
||
|
|
set_saxon_worker_pool(None)
|
||
|
|
logger.info("Saxon-Worker-Pool beendet")
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Fehler beim Beenden des Saxon-Worker-Pools: {e}")
|
||
|
|
|
||
|
|
def _initialize_fop_worker_pool(self):
|
||
|
|
"""Initialisiert den FOP-Worker-Pool für schnelle PDF-Generierung."""
|
||
|
|
try:
|
||
|
|
# Shutdown vorherigen Pool falls vorhanden
|
||
|
|
self._shutdown_fop_worker_pool()
|
||
|
|
|
||
|
|
# Prüfe ob FopWorkerPool aktiviert ist
|
||
|
|
if not app_settings.use_fop_worker_pool:
|
||
|
|
logger.info("FopWorkerPool deaktiviert - Verwende Fallback-Modus (subprocess)")
|
||
|
|
return
|
||
|
|
|
||
|
|
if not self.project:
|
||
|
|
logger.warning("Kein Projekt geladen, FOP-Worker-Pool nicht initialisiert")
|
||
|
|
return
|
||
|
|
|
||
|
|
# Hole Tool-Konfigurationen
|
||
|
|
java_vm = next((vm for vm in app_settings.java_vms if vm.id == self.project.java_vm_id), None)
|
||
|
|
apache_fop = next((fop for fop in app_settings.apache_fops if fop.id == self.project.apache_fop_id), None)
|
||
|
|
|
||
|
|
if not java_vm or not apache_fop:
|
||
|
|
logger.warning("Java VM oder Apache FOP nicht gefunden, Pool nicht initialisiert")
|
||
|
|
return
|
||
|
|
|
||
|
|
# FOP-Konfigurationsdatei (falls vorhanden)
|
||
|
|
fop_config_file = None
|
||
|
|
if self.project.fop_config_dir:
|
||
|
|
fop_config_file = self.project.fop_config_dir / "fop.xconf"
|
||
|
|
else:
|
||
|
|
default_config = apache_fop.path_to_dir / "conf" / "fop.xconf"
|
||
|
|
if default_config.exists():
|
||
|
|
fop_config_file = default_config
|
||
|
|
|
||
|
|
# Importiere FopWorkerPool
|
||
|
|
from fop_pool import FopWorkerPool
|
||
|
|
from transform import set_fop_worker_pool
|
||
|
|
|
||
|
|
# Erstelle Worker-Pool
|
||
|
|
num_workers = app_settings.max_workers
|
||
|
|
log_dir = self.project.project_dir / "temp"
|
||
|
|
pool = FopWorkerPool(
|
||
|
|
num_workers=num_workers,
|
||
|
|
java_vm_path=java_vm.path_to_binary_file,
|
||
|
|
apache_fop_dir=apache_fop.path_to_dir,
|
||
|
|
fop_config_file=fop_config_file,
|
||
|
|
log_dir=log_dir,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Setze globalen Pool
|
||
|
|
set_fop_worker_pool(pool)
|
||
|
|
|
||
|
|
logger.info(
|
||
|
|
f"FOP-Worker-Pool initialisiert: {num_workers} Worker "
|
||
|
|
f"(erwartet: {num_workers}x schneller für PDF-Generierung)"
|
||
|
|
)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Fehler beim Initialisieren des FOP-Worker-Pools: {e}")
|
||
|
|
logger.info("Fallback auf subprocess-Modus")
|
||
|
|
# Kein Pool ist OK - Fallback auf subprocess
|
||
|
|
|
||
|
|
def _shutdown_fop_worker_pool(self):
|
||
|
|
"""Beendet den FOP-Worker-Pool sauber."""
|
||
|
|
try:
|
||
|
|
# Importiere transform um Zugriff auf globalen Pool zu haben
|
||
|
|
import transform
|
||
|
|
|
||
|
|
if transform._fop_worker_pool:
|
||
|
|
logger.info("Beende FOP-Worker-Pool...")
|
||
|
|
transform._fop_worker_pool.shutdown()
|
||
|
|
# Importiere set_fop_worker_pool
|
||
|
|
from transform import set_fop_worker_pool
|
||
|
|
|
||
|
|
set_fop_worker_pool(None)
|
||
|
|
logger.info("FOP-Worker-Pool beendet")
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Fehler beim Beenden des FOP-Worker-Pools: {e}")
|
||
|
|
|
||
|
|
def _show_worker_pool_metrics(self):
|
||
|
|
"""Zeigt den Worker-Pool-Metriken-Dialog an."""
|
||
|
|
try:
|
||
|
|
from ui.WorkerPoolMetricsDialog import WorkerPoolMetricsDialog
|
||
|
|
|
||
|
|
dialog = WorkerPoolMetricsDialog(self)
|
||
|
|
dialog.exec()
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Fehler beim Öffnen des Metriken-Dialogs: {e}")
|
||
|
|
QMessageBox.critical(self, "Fehler", f"Fehler beim Öffnen des Metriken-Dialogs:\n{str(e)}")
|