1 /***
2 * Copyright 2003-2010 Terracotta, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package net.sf.ehcache.writer;
18
19 import net.sf.ehcache.CacheEntry;
20 import net.sf.ehcache.CacheException;
21 import net.sf.ehcache.Element;
22
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29
30 public class TestCacheWriterRetries extends AbstractTestCacheWriter {
31 private final int retries;
32 private final List<WriterEvent> writerEvents = new ArrayList<WriterEvent>();
33 private final Map<Object, Integer> retryCount = new HashMap<Object, Integer>();
34 private final Map<Object, Integer> writeCount = new HashMap<Object, Integer>();
35 private final Map<Object, Integer> deleteCount = new HashMap<Object, Integer>();
36
37 public TestCacheWriterRetries(int retries) {
38 this.retries = retries;
39 }
40
41 public List<WriterEvent> getWriterEvents() {
42 return writerEvents;
43 }
44
45 public Map<Object, Integer> getWriteCount() {
46 return writeCount;
47 }
48
49 public Map<Object, Integer> getDeleteCount() {
50 return deleteCount;
51 }
52
53 private void failUntilNoMoreRetries(Object key) {
54 int remainingRetries;
55 if (!retryCount.containsKey(key)) {
56 remainingRetries = retries;
57 } else {
58 remainingRetries = retryCount.get(key);
59 }
60 if (remainingRetries-- > 0) {
61 retryCount.put(key, remainingRetries);
62 throw new RuntimeException("Throwing exception to test retries, " + remainingRetries + " remaining for " + key);
63 }
64 retryCount.remove(key);
65 }
66
67 private void increaseWriteCount(Object key) {
68 if (!writeCount.containsKey(key)) {
69 writeCount.put(key, 1);
70 } else {
71 writeCount.put(key, writeCount.get(key) + 1);
72 }
73 }
74
75 private void increaseDeleteCount(Object key) {
76 if (!deleteCount.containsKey(key)) {
77 deleteCount.put(key, 1);
78 } else {
79 deleteCount.put(key, deleteCount.get(key) + 1);
80 }
81 }
82
83 private void put(Object key, Element element) {
84 writerEvents.add(new WriterEvent(element));
85 increaseWriteCount(key);
86 }
87
88 @Override
89 public synchronized void write(Element element) throws CacheException {
90 final Object key = element.getObjectKey();
91 failUntilNoMoreRetries(key);
92 put(key, element);
93 }
94
95 @Override
96 public synchronized void writeAll(Collection<Element> elements) throws CacheException {
97 Iterator<Element> it = elements.iterator();
98 while (it.hasNext()) {
99 Element element = it.next();
100
101 final Object key = element.getObjectKey();
102 if (!it.hasNext()) {
103 failUntilNoMoreRetries(key);
104 }
105 put(key, element);
106 }
107 }
108
109 private void remove(Object key) {
110 writerEvents.add(new WriterEvent(key));
111 increaseDeleteCount(key);
112 }
113
114 @Override
115 public synchronized void delete(CacheEntry entry) throws CacheException {
116 Object key = entry.getKey();
117 failUntilNoMoreRetries(key);
118 remove(key);
119 }
120
121 @Override
122 public synchronized void deleteAll(Collection<CacheEntry> entries) throws CacheException {
123 Iterator<CacheEntry> it = entries.iterator();
124 while (it.hasNext()) {
125 CacheEntry entry = it.next();
126 Object key = entry.getKey();
127 if (!it.hasNext()) {
128 failUntilNoMoreRetries(key);
129 }
130 remove(key);
131 }
132 }
133
134 class WriterEvent {
135
136 private final Object removedKey;
137 private final Element addedElement;
138 private final long time;
139 private final int writtenSize;
140 private final Map<Object, Integer> writeCount;
141 private final Map<Object, Integer> deleteCount;
142
143 WriterEvent(Object key) {
144 this.removedKey = key;
145 this.addedElement = null;
146 time = System.nanoTime();
147 writtenSize = TestCacheWriterRetries.this.writerEvents.size();
148 writeCount = new HashMap<Object, Integer>(TestCacheWriterRetries.this.writeCount);
149 deleteCount = new HashMap<Object, Integer>(TestCacheWriterRetries.this.deleteCount);
150 }
151
152 WriterEvent(Element element) {
153 this.removedKey = null;
154 this.addedElement = element;
155 time = System.nanoTime();
156 writtenSize = TestCacheWriterRetries.this.writerEvents.size();
157 writeCount = new HashMap<Object, Integer>(TestCacheWriterRetries.this.writeCount);
158 deleteCount = new HashMap<Object, Integer>(TestCacheWriterRetries.this.deleteCount);
159 }
160
161 int getWrittenSize() {
162 return writtenSize;
163 }
164
165 int getWriteCount(Object key) {
166 Integer value = writeCount.get(key);
167 if (value == null) {
168 return 0;
169 } else {
170 return value;
171 }
172 }
173
174 int getDeleteCount(Object key) {
175 Integer value = deleteCount.get(key);
176 if (value == null) {
177 return 0;
178 } else {
179 return value;
180 }
181 }
182
183 long getTime() {
184 return time;
185 }
186
187 Element getAddedElement() {
188 return addedElement;
189 }
190
191 Object getRemovedKey() {
192 return removedKey;
193 }
194 }
195 }