Package org.exist.management.impl

Source Code of org.exist.management.impl.SanityReport

/*
*  eXist Open Source Native XML Database
*  Copyright (C) 2001-10 The eXist Project
*  http://exist-db.org
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*
* $Id$
*/
package org.exist.management.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import javax.management.AttributeChangeNotification;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;

import org.apache.log4j.Logger;
import org.exist.EXistException;
import org.exist.backup.ErrorReport;
import org.exist.management.TaskStatus;
import org.exist.security.xacml.AccessContext;
import org.exist.source.StringSource;
import org.exist.storage.BrokerPool;
import org.exist.storage.ConsistencyCheckTask;
import org.exist.storage.DBBroker;
import org.exist.storage.SystemTask;
import org.exist.storage.XQueryPool;
import org.exist.xquery.CompiledXQuery;
import org.exist.xquery.XQuery;
import org.exist.xquery.XQueryContext;

public class SanityReport extends NotificationBroadcasterSupport implements SanityReportMBean {

    private final static Logger LOG = Logger.getLogger(SanityReport.class.getName());

    public final static String STATUS_OK = "OK";
    public final static String STATUS_FAIL = "FAIL";

    public final static StringSource TEST_XQUERY = new StringSource("<r>{current-dateTime()}</r>");
   
    public final static int PING_WAITING = -1;
    public final static int PING_ERROR = -2;
   
    private static String[] itemNames = { "errcode", "description" };
    private static String[] itemDescriptions = { "Error code", "Description of the error" };
    private static String[] indexNames = { "errcode" };

    private static List<ErrorReport> NO_ERRORS = new LinkedList<ErrorReport>();

    private int seqNum = 0;

    private Date actualCheckStart = null;

    private Date lastCheckStart = null;

    private Date lastCheckEnd = null;

    private String lastActionInfo = "nothing done";

    private long lastPingRespTime = 0;
   
    private String output = "";

    private TaskStatus taskstatus = new TaskStatus(TaskStatus.Status.NEVER_RUN);

    private List<ErrorReport> errors = NO_ERRORS;

    private BrokerPool pool;
   
    public SanityReport(BrokerPool pool) {
        this.pool = pool;
    }

    @Override
    public MBeanNotificationInfo[] getNotificationInfo() {
        final String[] types = new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE };
        final String name = AttributeChangeNotification.class.getName();
        final String description = "The status attribute of this MBean has changed";
        final MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description);
        return new MBeanNotificationInfo[] { info };
    }

    @Override
    public Date getLastCheckEnd() {
        return lastCheckEnd;
    }

    @Override
    public Date getLastCheckStart() {
        return lastCheckStart;
    }

    @Override
    public Date getActualCheckStart() {
        return actualCheckStart;
    }

    @Override
    public String getStatus() {
        return taskstatus.getStatusString();
    }

    @Override
    public String getLastActionInfo() {
        return lastActionInfo;
    }

    @Override
    public long getPingTime() {
      return lastPingRespTime;
    }
   
    @Override
    public TabularData getErrors() {
        final OpenType<?>[] itemTypes = { SimpleType.STRING, SimpleType.STRING };
        CompositeType infoType;
        try {
            infoType = new CompositeType("errorInfo", "Provides information on a consistency check error", itemNames,
                    itemDescriptions, itemTypes);
            final TabularType tabularType = new TabularType("errorList", "List of consistency check errors", infoType, indexNames);
            final TabularDataSupport data = new TabularDataSupport(tabularType);
            for (final ErrorReport error : errors) {
                final Object[] itemValues = { error.getErrcodeString(), error.getMessage() };
                data.put(new CompositeDataSupport(infoType, itemNames, itemValues));
            }
            return data;

        } catch (final OpenDataException e) {
            LOG.warn(e.getMessage(), e);
            return null;
        }
    }

    @Override
    public void triggerCheck(String output, String backup, String incremental) {
        try {
            this.output = output;
            final SystemTask task = new ConsistencyCheckTask();
            final Properties properties = parseParameter(output, backup, incremental);
            task.configure(pool.getConfiguration(), properties);
            pool.triggerSystemTask(task);

        } catch (final EXistException existException) {
            taskstatus.setStatus(TaskStatus.Status.STOPPED_ERROR);

            final List<ErrorReport> errors = new ArrayList<>();
            errors.add(
                new ErrorReport(
                    ErrorReport.CONFIGURATION_FAILD,
                    existException.getMessage(), existException));

            taskstatus.setReason(errors);
            changeStatus(taskstatus);
            taskstatus.setStatusChangeTime();
            taskstatus.setReason(existException.toString());
            LOG.warn("Failed to trigger db sanity check: " + existException.getMessage(), existException);
        }
    }

    @Override
    public long ping(boolean checkQueryEngine) {
      final long start = System.currentTimeMillis();
      lastPingRespTime = -1;
      lastActionInfo = "Ping";
     
      taskstatus.setStatus(TaskStatus.Status.PING_WAIT);
     
      DBBroker broker = null;
      try {
        // try to acquire a broker. If the db is deadlocked or not responsive,
        // this will block forever.
        broker = pool.get(pool.getSecurityManager().getGuestSubject());
       
        if (checkQueryEngine) {
          final XQuery xquery = broker.getXQueryService();
          final XQueryPool xqPool = xquery.getXQueryPool();
          CompiledXQuery compiled = xqPool.borrowCompiledXQuery(broker, TEST_XQUERY);
          if (compiled == null) {
            final XQueryContext context = xquery.newContext(AccessContext.TEST);
            compiled = xquery.compile(context, TEST_XQUERY);
          }
        try {
          xquery.execute(compiled, null);
        } finally {
          xqPool.returnCompiledXQuery(TEST_XQUERY, compiled);
        }
        }
      } catch (final Exception e) {
      lastPingRespTime = -2;
      taskstatus.setStatus(TaskStatus.Status.PING_ERROR);
      taskstatus.setStatusChangeTime();
      taskstatus.setReason(e.getMessage());
            changeStatus(taskstatus);

    } finally {
        pool.release(broker);
       
        lastPingRespTime = System.currentTimeMillis() - start;
        taskstatus.setStatus(TaskStatus.Status.PING_OK);
      taskstatus.setStatusChangeTime();
      taskstatus.setReason("ping response time: " + lastPingRespTime);
      changeStatus(taskstatus);
      }
    return lastPingRespTime;
    }
   
    private Properties parseParameter(String output, String backup, String incremental) {
        final Properties properties = new Properties();
        final boolean doBackup = backup.equalsIgnoreCase("YES");

        // This should be simplified
        if (backup != null && (doBackup) || backup.equalsIgnoreCase("no")) {
            properties.put("backup", backup);
        }

        if (incremental != null && (incremental.equalsIgnoreCase("YES") || incremental.equalsIgnoreCase("no"))) {
            properties.put("incremental", incremental);
        }

        if (output != null) {
            properties.put("output", output);
        } else {
            properties.put("backup", "no");
        }

        return properties;
    }

    protected void updateErrors(List<ErrorReport> errorList) {
        try {
            if (errorList == null || errorList.isEmpty()) {
                taskstatus.setStatus(TaskStatus.Status.STOPPED_OK);
                this.errors = NO_ERRORS;
            } else {
                this.errors = errorList;
                taskstatus.setStatus(TaskStatus.Status.STOPPED_ERROR);
            }
        } catch (final Exception e) {
            // ignore
        }

    }

    protected void changeStatus(TaskStatus status) {
        status.setStatusChangeTime();
        switch (status.getStatus()) {
            case INIT:
                actualCheckStart = status.getStatusChangeTime();
                break;
            case STOPPED_ERROR:
            case STOPPED_OK:
                lastCheckStart = actualCheckStart;
                actualCheckStart = null;
                lastCheckEnd = status.getStatusChangeTime();
                if (status.getReason() != null) {
                    this.errors = (List<ErrorReport>) status.getReason();
                }
                lastActionInfo = taskstatus.toString() + " to [" + output + "] ended with status [" + status.toString() + "]";
                break;
            default:
                break;
        }

        final TaskStatus oldState = taskstatus;
        try {
            taskstatus = status;
            final Notification event = new AttributeChangeNotification(this, seqNum++, taskstatus.getStatusChangeTime().getTime(),
                    "Status change", "status", "String", oldState.toString(), taskstatus.toString());
            event.setUserData(taskstatus.getCompositeData());
            sendNotification(event);
        } catch (final Exception e) {
            // ignore
        }
    }

    protected void updateStatus(int percentage) {
        try {
            final int oldPercentage = taskstatus.getPercentage();
            taskstatus.setPercentage(percentage);
            final Notification event = new AttributeChangeNotification(this, seqNum++, taskstatus.getStatusChangeTime().getTime(),
                    "Work percentage change", "status", "int", String.valueOf(oldPercentage), String.valueOf(taskstatus
                            .getPercentage()));
            event.setUserData(taskstatus.getCompositeData());
            sendNotification(event);
        } catch (final Exception e) {
            // ignore
        }
    }
}
TOP

Related Classes of org.exist.management.impl.SanityReport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.