/**
   * This service method stores an event in XML format in the lighthouse database. It does not
   * commit the current unit of work, which has to be done by the caller.
   *
   * @param event the XML of the event to log.
   * @throws PersistenceException in case of a database problem.
   * @throws XMLSerializationException in case of a problem with the event XML.
   */
  public void log(String eventXml) {
    if (log.isDebugEnabled()) log.debug("Logging the following event XML : " + eventXml);
    if (eventXml.getBytes().length >= EVENT_SIZE_LIMIT) {
      log.warn(
          "Log message exceeds maximum allowed log message size of "
              + EVENT_SIZE_LIMIT
              + " Byte. Message will be discarded.");
    }

    Event eventToLog = new Event();

    int retries = 3;
    while (true) {
      try {
        try {
          eventToLog.fromXml(eventXml, this.deploymentRegistry, this.softwareComponentRegistry);
        } catch (XMLSerializationException ex) {
          log.error("Could not parse event to log:\n" + eventXml + "\n", ex);
          throw ex;
        } catch (UnknownContextException unknownContextException) {
          if (log.isDebugEnabled()) {
            log.debug("Event could not be parsed due to unknown context: " + eventXml);
          }
          if (autoDeployUnknownEvents) {
            createContextForEvent(eventXml);
            eventToLog.fromXml(eventXml, this.deploymentRegistry, this.softwareComponentRegistry);
          } else {
            log.error("Could not parse event to log:\n" + eventXml + "\n", unknownContextException);
            throw new XMLSerializationException(
                unknownContextException.getMessage(), unknownContextException);
          }
        }

        this.log(eventToLog);

        if (log.isDebugEnabled()) {
          log.debug("Logged event XML");
        }
        break;

      } catch (Throwable ex) {
        log.warn("Failed to persist event: " + eventXml, ex);
        eventRegistry.getUnitOfWork().rollback();
        if (--retries == 0) {
          break;
        }
      }
    }
  }
    /** Perform event filter registration. */
    public void run() {
      if (log.isDebugEnabled()) {
        log.debug("Registering event filter " + this.eventFilter.toString());
        log.debug("Looking up matching past events in registry");
      }
      hibernateEventRegistry = (EventRegistry) getEventRegistry();
      unitOfWork = hibernateEventRegistry.getUnitOfWork();

      List<Event> matchesInRegistry =
          hibernateEventRegistry.findByTemplate(this.eventFilter.getTemplate());

      if (log.isDebugEnabled())
        log.debug("Matching past events found in registry, publishing them");

      List<Event> pastEventNotificationBatch = new ArrayList<Event>();

      for (Event match : matchesInRegistry) {
        if (!this.registrationHasBeenCanceled()) {
          pastEventNotificationBatch.add(match);

          if (pastEventNotificationBatch.size() % getPastEventNotificationBatchSize() == 0) {
            this.eventLoggerService
                .getEventFilterMatchHandler()
                .handleMatches(this.eventFilter, pastEventNotificationBatch);
            pastEventNotificationBatch.clear();
          }
        } else {
          if (log.isDebugEnabled())
            log.debug("Event filter has been deregistered. Stopping processing");

          unitOfWork.rollback();
          return;
        }
      }

      if (!pastEventNotificationBatch.isEmpty())
        this.eventLoggerService
            .getEventFilterMatchHandler()
            .handleMatches(this.eventFilter, pastEventNotificationBatch);

      this.eventLoggerService.getEventRegistry().getUnitOfWork().rollback();

      if (log.isDebugEnabled())
        log.debug("Matching past events published, now registering filter for live events");

      boolean performedLiveEventFilterRegistration = false;

      if (!this.registrationHasBeenCanceled()) {
        this.eventLoggerService.registerFilterForLiveEvents(this.eventFilter);
        performedLiveEventFilterRegistration = true;
      } else {
        if (log.isDebugEnabled())
          log.debug("Event filter has been deregistered. Not registering for live events anymore.");
        unitOfWork.rollback();
        return;
      }

      if (this.registrationHasBeenCanceled() && performedLiveEventFilterRegistration) {
        if (log.isDebugEnabled())
          log.debug(
              "Event filter has been deregistered while registering for live events. Deregistering again for safety reasons.");

        this.eventLoggerService.deregisterEventFilter(this.eventFilter.getUuid());
      }

      this.eventLoggerService.handlerFinishedEventRegistration(this.eventFilter.getUuid());

      if (log.isDebugEnabled()) log.debug("Event filter registered for live events.");
      unitOfWork.rollback();
    }