001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.cache.ehcache;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.InitialThreadLocal;
021    
022    import java.util.ArrayList;
023    import java.util.List;
024    import java.util.Properties;
025    
026    import net.sf.ehcache.CacheException;
027    import net.sf.ehcache.Ehcache;
028    import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
029    
030    /**
031     * @author Shuyang Zhou
032     * @author Sherry Yang
033     */
034    public class EhcacheStreamBootstrapCacheLoader implements BootstrapCacheLoader {
035    
036            public static void resetSkip() {
037                    _skipBootstrapThreadLocal.remove();
038            }
039    
040            public static void setSkip() {
041                    _skipBootstrapThreadLocal.set(Boolean.TRUE);
042            }
043    
044            public static synchronized void start() {
045                    if (!_started) {
046                            _started = true;
047                    }
048    
049                    if (_log.isDebugEnabled()) {
050                            _log.debug("Loading deferred caches");
051                    }
052    
053                    try {
054                            EhcacheStreamBootstrapHelpUtil.loadCachesFromCluster(
055                                    true,
056                                    _deferredEhcaches.toArray(
057                                            new Ehcache[_deferredEhcaches.size()]));
058                    }
059                    catch (Exception e) {
060                            throw new CacheException(e);
061                    }
062                    finally {
063                            _deferredEhcaches.clear();
064                    }
065            }
066    
067            public EhcacheStreamBootstrapCacheLoader(Properties properties) {
068                    if (properties != null) {
069                            _bootstrapAsynchronously = GetterUtil.getBoolean(
070                                    properties.getProperty("bootstrapAsynchronously"));
071                    }
072            }
073    
074            @Override
075            public Object clone() {
076                    return this;
077            }
078    
079            public void doLoad(Ehcache ehcache) {
080                    synchronized (EhcacheStreamBootstrapCacheLoader.class) {
081                            if (!_started) {
082                                    _deferredEhcaches.add(ehcache);
083    
084                                    return;
085                            }
086                    }
087    
088                    if (_skipBootstrapThreadLocal.get()) {
089                            return;
090                    }
091    
092                    if (_log.isDebugEnabled()) {
093                            _log.debug("Bootstraping " + ehcache.getName());
094                    }
095    
096                    try {
097                            EhcacheStreamBootstrapHelpUtil.loadCachesFromCluster(
098                                    false, ehcache);
099                    }
100                    catch (Exception e) {
101                            throw new CacheException(e);
102                    }
103            }
104    
105            @Override
106            public boolean isAsynchronous() {
107                    return _bootstrapAsynchronously;
108            }
109    
110            @Override
111            public void load(Ehcache ehcache) {
112                    if (_bootstrapAsynchronously) {
113                            EhcacheStreamClientThread streamBootstrapThread =
114                                    new EhcacheStreamClientThread(ehcache);
115    
116                            streamBootstrapThread.start();
117                    }
118                    else {
119                            doLoad(ehcache);
120                    }
121            }
122    
123            private static Log _log = LogFactoryUtil.getLog(
124                    EhcacheStreamBootstrapCacheLoader.class);
125    
126            private static List<Ehcache> _deferredEhcaches = new ArrayList<Ehcache>();
127            private static ThreadLocal<Boolean> _skipBootstrapThreadLocal =
128                    new InitialThreadLocal<Boolean>(
129                            EhcacheStreamBootstrapCacheLoader.class +
130                                    "._skipBootstrapThreadLocal",
131                            false);
132            private static boolean _started;
133    
134            private boolean _bootstrapAsynchronously = true;
135    
136            private class EhcacheStreamClientThread extends Thread {
137    
138                    public EhcacheStreamClientThread(Ehcache ehcache) {
139                            if (_log.isDebugEnabled()) {
140                                    _log.debug(
141                                            "Ehcache stream client thread for cache " +
142                                                    ehcache.getName());
143                            }
144    
145                            _ehcache = ehcache;
146    
147                            setDaemon(true);
148                            setName(
149                                    EhcacheStreamClientThread.class.getName() + " - " +
150                                            ehcache.getName());
151                            setPriority(Thread.NORM_PRIORITY);
152                    }
153    
154                    @Override
155                    public void run() {
156                            try {
157                                    doLoad(_ehcache);
158                            }
159                            catch (Exception e) {
160                                    if (_log.isWarnEnabled()) {
161                                            _log.warn("Unable to asynchronously stream bootstrap", e);
162                                    }
163                            }
164                    }
165    
166                    private Ehcache _ehcache;
167    
168            }
169    
170    }