Files
xsl-validator/src/ui/mixins/worker_pool.py
T

193 lines
7.7 KiB
Python
Raw Normal View History

"""
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 / "tmp"
# 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 / "tmp"
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)}")