View Javadoc

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             // fail on the last item in the batch
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 }