docs: @Override
    public void end(Xid xid, int flags) throws XAException {
      if (LOGGER.isLoggable(Level.FINEST)) {
        debug("ending transaction xid = " + xid);
      }
  
      // Check preconditions
  
      if (flags != XAResource.TMSUSPEND && flags != XAResource.TMFAIL
          && flags != XAResource.TMSUCCESS) {
        throw new PGXAException(GT.tr("Invalid flags {0}", flags), XAException.XAER_INVAL);
      }
  
      if (xid == null) {
        throw new PGXAException(GT.tr("xid must not be null"), XAException.XAER_INVAL);
      }
  
      if (state != State.ACTIVE || !currentXid.equals(xid)) {
        throw new PGXAException(GT.tr("tried to call end without corresponding start call. state={0}, start xid={1}, currentXid={2}, preparedXid={3}", state, xid, currentXid, preparedXid),
            XAException.XAER_PROTO);
      }
  
      // Check implementation deficiency preconditions
      if (flags == XAResource.TMSUSPEND) {
        throw new PGXAException(GT.tr("suspend/resume not implemented"), XAException.XAER_RMERR);
      }
  
      // We ignore TMFAIL. It's just a hint to the RM. We could roll back immediately
      // if TMFAIL was given.
  
      // All clear. We don't have any real work to do.
      state = State.ENDED;
    }