/
ClassSpecificEvictionStrategy.java
147 lines (125 loc) · 5.52 KB
/
ClassSpecificEvictionStrategy.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*******************************************************************************
* Copyright (c) 2012 GigaSpaces Technologies Ltd. All
rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.openspaces.eviction.specificorder;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.logging.Level;
import org.openspaces.eviction.AbstractClassBasedEvictionStrategy;
import org.openspaces.eviction.OrderBy;
import org.openspaces.eviction.Priority;
import org.openspaces.eviction.SpaceEvictionPriority;
import com.gigaspaces.server.eviction.EvictableServerEntry;
import com.gigaspaces.server.eviction.SpaceEvictionManager;
import com.gigaspaces.server.eviction.SpaceEvictionStrategy;
import com.gigaspaces.server.eviction.SpaceEvictionStrategyConfig;
/**
* This class enables a class specific eviction mechanism
* this means eviction is first by the priority indicated by the class,
* if there are several classes with the same priority classes will be picked by
* the hash code number of their class object.
* After a class was picked for eviction the eviction strategy to be used is according
* to what has been indicated in the classes' {@link SpaceEvictionPriority} {@link OrderBy} property
*
* @author Sagi Bernstein
* @since 9.1.0
*/
public class ClassSpecificEvictionStrategy extends AbstractClassBasedEvictionStrategy{
public static final int MAX_THREADS = 100;
ConcurrentSkipListMap<Priority, ConcurrentHashMap<Integer, SpaceEvictionStrategy>> priorities;
@Override
public void initialize(SpaceEvictionManager evictionManager, SpaceEvictionStrategyConfig config){
super.initialize(evictionManager, config);
priorities = new ConcurrentSkipListMap<Priority, ConcurrentHashMap<Integer, SpaceEvictionStrategy>>();
}
@Override
public void onInsert(EvictableServerEntry entry){
int classHash = getEntryClassHash(entry);
Priority priority = getPriority(entry);
//handle priority value is first inserted to space
if(getPriorities().putIfAbsent(priority, new ConcurrentHashMap<Integer, SpaceEvictionStrategy>()) == null)
if(logger.isLoggable(Level.FINER))
logger.finer("opened new priority listing for priority: " + getPriority(entry));
//handle class type is first inserted to space
if(!getPriorities().get(priority).containsKey(classHash)){
switch(getOrderBy(entry)){
case FIFO:
ClassSpecificEvictionFIFOStrategy fifoStrategy = new ClassSpecificEvictionFIFOStrategy(getEvictionManager());
fifoStrategy.initialize(getEvictionManager(), getEvictionConfig());
getPriorities().get(priority).putIfAbsent(classHash, fifoStrategy);
if(logger.isLoggable(Level.FINER))
logger.finer("created new FIFO strategy for class " +
entry.getSpaceTypeDescriptor().getObjectClass());
break;
case LRU:
ClassSpecificEvictionLRUStrategy lruStrategy = new ClassSpecificEvictionLRUStrategy(getEvictionManager());
lruStrategy.initialize(getEvictionManager(), getEvictionConfig());
getPriorities().get(priority).putIfAbsent(classHash, lruStrategy);
if(logger.isLoggable(Level.FINER))
logger.finer("created new LRU strategy for class " +
entry.getSpaceTypeDescriptor().getObjectClass());
break;
case NONE:
getPriorities().get(priority).putIfAbsent(classHash, new ClassSpecificEvictionNoneStrategy());
if(logger.isLoggable(Level.FINER))
logger.finer("created new NONE strategy for class " +
entry.getSpaceTypeDescriptor().getObjectClass());
}
}
getSpecificStrategy(entry).onInsert(entry);
}
@Override
public void onLoad(EvictableServerEntry entry){
onInsert(entry);
}
@Override
public void onRead(EvictableServerEntry entry){
getSpecificStrategy(entry).onRead(entry);
}
@Override
public void onUpdate(EvictableServerEntry entry){
getSpecificStrategy(entry).onUpdate(entry);
}
@Override
public void onRemove(EvictableServerEntry entry){
getSpecificStrategy(entry).onRemove(entry);
}
@Override
public int evict(int evictionQuota){
int counter = 0;
for(ConcurrentHashMap<Integer, SpaceEvictionStrategy> priorityLevel : getPriorities().values()){
if(counter == evictionQuota)
break;
if(priorityLevel.isEmpty())
continue;
for (SpaceEvictionStrategy strategy : priorityLevel.values()) {
counter += strategy.evict(evictionQuota - counter);
if(counter == evictionQuota)
break;
}
}
return counter;
}
public ConcurrentSkipListMap<Priority, ConcurrentHashMap<Integer, SpaceEvictionStrategy>> getPriorities() {
return priorities;
}
private int getEntryClassHash(EvictableServerEntry entry) {
return entry.getSpaceTypeDescriptor().getObjectClass().hashCode();
}
protected SpaceEvictionStrategy getSpecificStrategy(EvictableServerEntry entry) {
return getPriorities().get(getPriority(entry)).get(getEntryClassHash(entry));
}
}