mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	12349: Tweaked the Hibernate session helper to prevent initially-large sessions from drowning the flush code 12452: MT - fix ETHREEOH-1056 12453: MT - fix ETHREEOH-886 12460: MT - fix ETHREEOH-1013 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@12536 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
			
				
	
	
		
			273 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2005-2007 Alfresco Software Limited.
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU 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 General Public License for more details.
 | |
| 
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program; if not, write to the Free Software
 | |
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | |
| 
 | |
|  * As a special exception to the terms and conditions of version 2.0 of 
 | |
|  * the GPL, you may redistribute this Program in connection with Free/Libre 
 | |
|  * and Open Source Software ("FLOSS") applications as described in Alfresco's 
 | |
|  * FLOSS exception.  You should have recieved a copy of the text describing 
 | |
|  * the FLOSS exception, and it is also available here: 
 | |
|  * http://www.alfresco.com/legal/licensing"
 | |
|  */
 | |
| package org.alfresco.repo.domain.hibernate;
 | |
| 
 | |
| import java.util.ArrayList;
 | |
| import java.util.HashSet;
 | |
| import java.util.LinkedHashMap;
 | |
| import java.util.List;
 | |
| import java.util.Set;
 | |
| 
 | |
| import org.alfresco.util.GUID;
 | |
| import org.hibernate.Session;
 | |
| import org.hibernate.engine.EntityKey;
 | |
| 
 | |
| /**
 | |
|  * Support to (optionally) listen to hibernate events generated by a hibernate session. The tracking is bound to a
 | |
|  * transaction resource
 | |
|  * 
 | |
|  * @author andyh
 | |
|  */
 | |
| public class HibernateSessionHelperResource implements HibernateSessionHelperResourceProvider
 | |
| {
 | |
|     LinkedHashMap<String, Set<EntityKey>> marks = new LinkedHashMap<String, Set<EntityKey>>();
 | |
| 
 | |
|     String currentMark = null;
 | |
| 
 | |
|     HibernateSessionHelperResource()
 | |
|     {
 | |
| 
 | |
|     }
 | |
| 
 | |
|     public String getCurrentMark()
 | |
|     {
 | |
|         return currentMark;
 | |
|     }
 | |
|     
 | |
|     public List<String> getMarks(Session session)
 | |
|     {
 | |
|         ArrayList<String> answer = new ArrayList<String>(marks.size());
 | |
|         for (String key : marks.keySet())
 | |
|         {
 | |
|             answer.add(key);
 | |
|         }
 | |
|         return answer;
 | |
|     }
 | |
| 
 | |
|     public void mark(Session session)
 | |
|     {
 | |
|         String guid = GUID.generate();
 | |
|         mark(session, guid);
 | |
|     }
 | |
| 
 | |
|     @SuppressWarnings("unchecked")
 | |
|     public void mark(Session session, String label)
 | |
|     {
 | |
|         if (label == null)
 | |
|         {
 | |
|             throw new HibernateSessionHelperResourceException("Null key is not supported");
 | |
| 
 | |
|         }
 | |
|         if (marks.containsKey(label))
 | |
|         {
 | |
|             throw new HibernateSessionHelperResourceException("Key already exists - " + label);
 | |
|         }
 | |
| 
 | |
|         if (marks.size() == 0)
 | |
|         {
 | |
|             SessionSizeResourceManager.setDisableInTransaction();
 | |
|         }
 | |
| 
 | |
|         HashSet<EntityKey> mark = new HashSet<EntityKey>((Set<EntityKey>) session.getStatistics().getEntityKeys());
 | |
|         
 | |
|         // If the mark is too large, then the flush process will be excessive.
 | |
|         if (mark.size() > 1000)
 | |
|         {
 | |
|             // The session is to big.  Use the mark to as a basis for cleaning out the session.
 | |
|             if (currentMark == null)
 | |
|             {
 | |
|                 // The session is just too big
 | |
|                 SessionSizeResourceManager.clear(session);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 reset(session);
 | |
|             }
 | |
|             // Get the mark list again
 | |
|             mark = new HashSet<EntityKey>((Set<EntityKey>) session.getStatistics().getEntityKeys());
 | |
|         }
 | |
|         
 | |
|         marks.put(label, mark);
 | |
|         currentMark = label;
 | |
|     }
 | |
| 
 | |
|     public void removeMark(Session session)
 | |
|     {
 | |
|         if (currentMark != null)
 | |
|         {
 | |
|             removeMark(session, currentMark);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             throw new HibernateSessionHelperResourceException("No current mark");
 | |
|         }
 | |
|         
 | |
|     }
 | |
| 
 | |
|     public void removeMark(Session session, String label)
 | |
|     {
 | |
|         if (label == null)
 | |
|         {
 | |
|             throw new HibernateSessionHelperResourceException("Null key is not supported");
 | |
| 
 | |
|         }
 | |
|         if (!marks.containsKey(label))
 | |
|         {
 | |
|             throw new HibernateSessionHelperResourceException("Key does not exist - " + label);
 | |
|         }
 | |
| 
 | |
|         if (marks.size() > 0)
 | |
|         {
 | |
|             marks.remove(label);
 | |
| 
 | |
|             if (label.equals(currentMark))
 | |
|             {
 | |
|                 currentMark = getLastMarkOrNull();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (marks.size() == 0)
 | |
|         {
 | |
|             SessionSizeResourceManager.setEnableInTransaction();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public void reset(Session session)
 | |
|     {
 | |
|         if (currentMark != null)
 | |
|         {
 | |
|             doResetAndRemove(session, currentMark, false);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             throw new HibernateSessionHelperResourceException("No current mark");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public void reset(Session session, String label)
 | |
|     {
 | |
|         doResetAndRemove(session, label, false);
 | |
|     }
 | |
| 
 | |
|     public void resetAndRemoveMark(Session session)
 | |
|     {
 | |
|         if (currentMark != null)
 | |
|         {
 | |
|             doResetAndRemove(session, currentMark, true);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             throw new HibernateSessionHelperResourceException("No current mark");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public void resetAndRemoveMark(Session session, String label)
 | |
|     {
 | |
|         doResetAndRemove(session, label, true);
 | |
|     }
 | |
| 
 | |
|     @SuppressWarnings("unchecked")
 | |
|     private void doResetAndRemove(Session session, String label, boolean remove)
 | |
|     {
 | |
|         if (label == null)
 | |
|         {
 | |
|             throw new HibernateSessionHelperResourceException("Null key is not supported");
 | |
| 
 | |
|         }
 | |
|         if (!marks.containsKey(label))
 | |
|         {
 | |
|             throw new HibernateSessionHelperResourceException("Key does not exist - " + label);
 | |
|         }
 | |
|         if (marks.size() > 0)
 | |
|         {
 | |
|             session.flush();
 | |
| 
 | |
|             Set<EntityKey> check = marks.get(label);
 | |
|             Set<EntityKey> current = new HashSet<EntityKey>((Set<EntityKey>) session.getStatistics().getEntityKeys());
 | |
| 
 | |
|             Set<Object> toEvict = new HashSet<Object>(Math.max((int) (current.size() / .75f) + 1, 16));
 | |
| 
 | |
|             for (EntityKey key : current)
 | |
|             {
 | |
|                 if (!check.contains(key))
 | |
|                 {
 | |
|                     if(key.getEntityName().equals(QNameEntityImpl.class.getName()))
 | |
|                     {
 | |
|                         //System.out.println("Skipping: " + key.getEntityName());
 | |
|                         continue;
 | |
|                     }
 | |
|                     Object val = session.get(key.getEntityName(), key.getIdentifier());
 | |
|                     if (val != null)
 | |
|                     {
 | |
|                         toEvict.add(val);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             for (Object evitee : toEvict)
 | |
|             {
 | |
|                 session.evict(evitee);
 | |
|             }
 | |
| 
 | |
|             String last;
 | |
|             while ((last = getLastMarkOrNull()) != null)
 | |
|             {
 | |
|                 if (!label.equals(last))
 | |
|                 {
 | |
|                     marks.remove(last);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     if (remove)
 | |
|                     {
 | |
|                         marks.remove(last);
 | |
|                     }
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             currentMark = getLastMarkOrNull();
 | |
| 
 | |
|             if (marks.size() == 0)
 | |
|             {
 | |
|                 SessionSizeResourceManager.setEnableInTransaction();
 | |
|             }
 | |
|             
 | |
|             //System.out.println("Removed "+marks.size()+" "+label);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private String getLastMarkOrNull()
 | |
|     {
 | |
|         String mark = null;
 | |
|         for (String key : marks.keySet())
 | |
|         {
 | |
|             mark = key;
 | |
|         }
 | |
|         return mark;
 | |
|     }
 | |
| 
 | |
| }
 |