001/*
002*  Copyright 2016 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013*  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.workspaces.repository.maintenance;
017
018import java.util.List;
019
020import javax.jcr.RepositoryException;
021import javax.jcr.Session;
022import javax.jcr.SimpleCredentials;
023
024import org.apache.jackrabbit.core.RepositoryContext;
025import org.apache.jackrabbit.core.id.NodeId;
026import org.apache.jackrabbit.core.persistence.IterablePersistenceManager;
027import org.apache.jackrabbit.core.persistence.PersistenceManager;
028import org.apache.jackrabbit.core.persistence.bundle.AbstractBundlePersistenceManager;
029import org.apache.jackrabbit.core.persistence.check.ConsistencyCheckListener;
030import org.apache.jackrabbit.core.persistence.check.ConsistencyReport;
031import org.apache.jackrabbit.core.persistence.check.ReportItem;
032import org.slf4j.LoggerFactory;
033
034import org.ametys.core.schedule.progression.ProgressionTrackerFactory;
035import org.ametys.runtime.i18n.I18nizableText;
036
037/**
038 * ConsistencyCheckTask
039 */
040public class ConsistencyCheckTask extends AbstractMaintenanceTask implements ConsistencyCheckListener
041{
042    /** The JCR Session bound to this task. */
043    protected Session _session;
044
045    private List<IterablePersistenceManager> _pmList;
046
047    @Override
048    protected void initialize() throws RepositoryException
049    {
050        // Create the repository and log in the session.
051        RepositoryContext repositoryContext = createRepositoryContext();
052        _session = repositoryContext.getRepository().login(new SimpleCredentials("__MAINTENANCE_TASK__", "".toCharArray()));
053
054        _pmList = getAllPersistenceManager(repositoryContext);
055
056        // Initialize the task progress object.
057        int count = 0; // number of item that will be scanned.
058
059        try
060        {
061            for (IterablePersistenceManager pm : _pmList)
062            {
063                List<NodeId> ids = pm.getAllNodeIds(null, 8192);
064
065                NodeId lastId = null;
066                while (!ids.isEmpty()) 
067                {
068                    count += ids.size();
069                    lastId = ids.get(ids.size() - 1);
070                    ids = pm.getAllNodeIds(lastId, 8192);
071                }
072            }
073            
074            _progress = ProgressionTrackerFactory.createContainerProgressionTracker(new I18nizableText("plugin.repositoryapp", "PLUGINS_REPOSITORYAPP_BUTTON_MAINTENANCE_CONSISTENCYCHECK"), _logger);
075            // count for the number of nodes, plus 1 for closing the task
076            _progress.setSize(count + 1);
077        }
078        catch (Exception e)
079        {
080            _progress.setSize(0);
081            _logger.error(e.getLocalizedMessage(), e);
082        }
083    }
084    
085    @Override
086    protected void setLogger()
087    {
088        setLogger(LoggerFactory.getLogger(ConsistencyCheckTask.class));
089    }
090
091    @Override
092    protected void apply() throws RepositoryException
093    {
094        for (PersistenceManager pm : _pmList)
095        {
096            // Do PM consistency check
097            if (pm instanceof AbstractBundlePersistenceManager abpm)
098            {
099                // Perform the check
100                // null -> all uuids, true -> recursive, false -> nofix, null, 
101                // lost+found -> null, this -> listener 
102                ConsistencyReport report = abpm.check(null, true, false, null, this);
103                int numberOfNodesChecked = report.getNodeCount();
104                
105                _logger.info("Consistency check done for persistence manager : '" + pm.toString() + "' in " + (report.getElapsedTimeMs() / 1000f) + " s.");
106                _logger.info(numberOfNodesChecked + " nodes were checked.");
107                _logger.info(report.getItems().isEmpty() ? "No consistency problems were reported." : report.getItems().size() + " consistency problems were reported."); 
108                
109                _progress.increment(numberOfNodesChecked);
110            }
111        }
112    }
113
114    @Override
115    protected void close()
116    {
117        if (_session != null)
118        {
119            _session.logout();
120        }
121        
122        // We need to close the session before shuting the repository down
123        super.close();
124        
125        if (_progress != null)
126        {
127            _progress.increment();
128        }
129    }
130
131    // Listener methods 
132
133    @Override
134    public void startCheck(String id)
135    {
136        // Do Nothing
137    }
138
139    @Override
140    public void report(ReportItem item)
141    {
142        _logger.warn(item.toString());
143    }
144
145    @Override
146    public void error(String id, String message)
147    {
148        _logger.error("error during the consistency check -> id : [ " + id + "]\n" + message);
149    }
150
151    @Override
152    public void info(String id, String message)
153    {
154        _logger.info("error during the consistency check -> id : [ " + id + "]\n" + message);
155    }
156}