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 */
016
017package org.ametys.web.cache.monitoring.process.access;
018
019import java.util.List;
020
021import org.apache.ibatis.session.SqlSession;
022
023import org.ametys.core.datasource.AbstractMyBatisDAO;
024import org.ametys.core.util.DateUtils;
025
026import com.google.common.collect.LinkedListMultimap;
027import com.google.common.collect.ListMultimap;
028
029/**
030 * The RessourceAccessMonitor collects the resources that have been requested,
031 * and export them into a database.
032 */
033public class ResourceAccessComponent extends AbstractMyBatisDAO
034{
035    /** Avalon ROLE. */
036    public static final String ROLE = ResourceAccessComponent.class.getName();
037    
038    /** List of pending {@link ResourceAccess} waiting to be exported to the database. */
039    protected ListMultimap<String, ResourceAccess> _pendingRecords = LinkedListMultimap.create();
040
041    /**
042     * Add a new {@link ResourceAccess} to the monitored resources.
043     * @param ra The resource access object.
044     */
045    public void addAccessRecord(ResourceAccess ra)
046    {
047        synchronized (this)
048        {
049            _pendingRecords.put(ra.getClass().getName(), ra);
050        }
051    }
052
053    /**
054     * Call this method to transfer pendings resource access from memory to database
055     * This is normally called by a scheduler
056     */
057    public void exportPendings()
058    {
059        long start = 0;
060        int successCount = 0;
061        ListMultimap<String, ResourceAccess> resourcesAccesstoExport;
062        
063        if (getLogger().isDebugEnabled())
064        {
065            getLogger().debug("Start to insert pending records.");
066            start = System.currentTimeMillis();
067        }
068        
069        // Copy the current pending records by switching references
070        synchronized (this)
071        {
072            resourcesAccesstoExport = _pendingRecords;
073            _pendingRecords = LinkedListMultimap.create();
074        }
075            
076        // Export
077        if (!resourcesAccesstoExport.isEmpty())
078        {
079            successCount = _fillDatabase(resourcesAccesstoExport);
080        }
081        
082        if (getLogger().isDebugEnabled())
083        {
084            String durationStr = DateUtils.formatDuration(System.currentTimeMillis() - start);
085            getLogger().debug(String.format("%s/%s pending records exported into database in %s", successCount, resourcesAccesstoExport.size(), durationStr));
086        }
087    }
088    
089    private int _fillDatabase(ListMultimap<String, ResourceAccess> resourcesAccess)
090    {
091        int success = 0;
092        for (String resourceAccessType : resourcesAccess.keySet())
093        {
094            try (SqlSession sqlSession = getSession())
095            {
096                success += _fillDatabase(sqlSession, resourcesAccess.get(resourceAccessType));
097                
098                // Commit the transaction.
099                sqlSession.commit();
100            }
101        }
102        return success;
103    }
104    
105    private int _fillDatabase(SqlSession sqlSession, List<ResourceAccess> resourcesAccess)
106    {
107        try
108        {
109            for (ResourceAccess ra : resourcesAccess)
110            {
111                sqlSession.insert(ra.getInsertStatementId(), ra.getInsertStatementParameters());
112            }
113            
114            return resourcesAccess.size();
115        }
116        catch (Exception e)
117        {
118            getLogger().error("Exception exception while inserting new records to the database", e);
119            return 0;
120        }
121    }
122}