/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.core.impl;
import org.drools.core.SessionConfiguration;
import org.kie.internal.concurrent.ExecutorProviderFactory;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
public class SessionsCache {
private final Map<SessionConfiguration, Queue<StatefulKnowledgeSessionImpl>> cleanSessions = new ConcurrentHashMap<SessionConfiguration, Queue<StatefulKnowledgeSessionImpl>>();
private final boolean isAsync;
SessionsCache(boolean isAsync) {
this.isAsync = isAsync;
}
public void store(StatefulKnowledgeSessionImpl session) {
if (isAsync) {
SessionResetterHolder.SESSION_RESETTER.enqueue(this, session);
} else {
session.reset();
storeResettedSession(session);
}
}
private void storeResettedSession(StatefulKnowledgeSessionImpl session) {
Queue<StatefulKnowledgeSessionImpl> cache = cleanSessions.get(session.getSessionConfiguration());
if (cache == null) {
cache = new ConcurrentLinkedQueue<StatefulKnowledgeSessionImpl>();
cleanSessions.put(session.getSessionConfiguration(), cache);
}
cache.offer(session);
}
public StatefulKnowledgeSessionImpl getCachedSession(SessionConfiguration config) {
Queue<StatefulKnowledgeSessionImpl> cache = cleanSessions.get(config);
return cache != null ? cache.poll() : null;
}
private static class SessionResetterHolder {
private static final SessionResetter SESSION_RESETTER = new SessionResetter();
}
private static class SessionResetter {
private final Executor executor = ExecutorProviderFactory.getExecutorProvider().newSingleThreadExecutor();
private final BlockingQueue<SessionSlot> dirtySessions = new ArrayBlockingQueue<SessionSlot>(20);
private SessionResetter() {
executor.execute(new Runnable() {
@Override
public void run() {
while (true) {
try {
dirtySessions.take().doReset();
} catch (InterruptedException e) { }
}
}
});
}
private void enqueue(SessionsCache sessionsCache, StatefulKnowledgeSessionImpl session) {
dirtySessions.offer(new SessionSlot(sessionsCache, session));
}
}
private static class SessionSlot {
private final SessionsCache sessionsCache;
private final StatefulKnowledgeSessionImpl session;
private SessionSlot(SessionsCache sessionsCache, StatefulKnowledgeSessionImpl session) {
this.sessionsCache = sessionsCache;
this.session = session;
}
private void doReset() {
session.reset();
sessionsCache.storeResettedSession(session);
}
}
}