EMMA Coverage Report (generated Tue Oct 27 11:32:50 PDT 2009)
[all classes][net.spy.memcached.util]

COVERAGE SUMMARY FOR SOURCE FILE [CacheLoader.java]

nameclass, %method, %block, %line, %
CacheLoader.java100% (2/2)89%  (8/9)84%  (123/147)81%  (30.6/38)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class CacheLoader100% (1/1)86%  (6/7)79%  (90/114)78%  (25.6/33)
CacheLoader (MemcachedClientIF): void 0%   (0/1)0%   (0/7)0%   (0/2)
push (String, Object): Future 100% (1/1)67%  (22/33)63%  (8.2/13)
loadData (Iterator): Future 100% (1/1)82%  (28/34)91%  (6.4/7)
CacheLoader (MemcachedClientIF, ExecutorService, CacheLoader$StorageListener,... 100% (1/1)100% (15/15)100% (6/6)
access$000 (CacheLoader): CacheLoader$StorageListener 100% (1/1)100% (3/3)100% (1/1)
loadData (Map): Future 100% (1/1)100% (6/6)100% (1/1)
watch (String, Future): void 100% (1/1)100% (16/16)100% (3/3)
     
class CacheLoader$1100% (1/1)100% (2/2)100% (33/33)100% (6/6)
CacheLoader$1 (CacheLoader, String, Future): void 100% (1/1)100% (12/12)100% (1/1)
run (): void 100% (1/1)100% (21/21)100% (5/5)

1package net.spy.memcached.util;
2 
3import java.util.Iterator;
4import java.util.Map;
5import java.util.concurrent.ExecutorService;
6import java.util.concurrent.Future;
7import java.util.concurrent.TimeUnit;
8 
9import net.spy.memcached.MemcachedClientIF;
10import net.spy.memcached.compat.SpyObject;
11import net.spy.memcached.internal.ImmediateFuture;
12 
13/**
14 * CacheLoader provides efficient mechanisms for storing lots of data.
15 */
16public class CacheLoader extends SpyObject {
17 
18        private final ExecutorService executorService;
19        private final StorageListener storageListener;
20        private final MemcachedClientIF client;
21        private final int expiration;
22 
23        /**
24         * Simple CacheLoader constructor that doesn't provide any feedback and
25         * caches forever.
26         *
27         * @param c a client
28         */
29        public CacheLoader(MemcachedClientIF c) {
30                this(c, null, null, 0);
31        }
32 
33        /**
34         * Get a CacheLoader with all the options.
35         *
36         * @param c a client
37         * @param es an ExecutorService (e.g. thread pool) to dispatch results
38         *           (may be null, in which case no listener may be provided)
39         * @param sl a storage listener (may be null)
40         * @param exp expiration to use while loading
41         */
42        public CacheLoader(MemcachedClientIF c, ExecutorService es,
43                        StorageListener sl, int exp) {
44                super();
45                client = c;
46                executorService = es;
47                storageListener = sl;
48                expiration = exp;
49        }
50 
51        /**
52         * Load data from the given iterator.
53         *
54         * @param <T> type of data being loaded
55         * @param i the iterator of data to load
56         */
57        public <T> Future<?> loadData(Iterator<Map.Entry<String, T>> i) {
58                Future<Boolean> mostRecent = null;
59                while(i.hasNext()) {
60                        Map.Entry<String, T> e = i.next();
61                        mostRecent = push(e.getKey(), e.getValue());
62                        watch(e.getKey(), mostRecent);
63                }
64 
65                return mostRecent == null ? new ImmediateFuture(true) : mostRecent;
66        }
67 
68        /**
69         * Load data from the given map.
70         *
71         * @param <T> type of data being loaded
72         * @param map the map of keys to values that needs to be loaded
73         */
74        public <T> Future<?> loadData(Map<String, T> map) {
75                return loadData(map.entrySet().iterator());
76        }
77 
78        /**
79         * Push a value into the cache.
80         *
81         * This is a wrapper around set that throttles and retries on full queues.
82         *
83         * @param <T> the type being stored
84         * @param k the key
85         * @param value the value
86         * @return the future representing the stored data
87         */
88        public <T> Future<Boolean> push(String k, T value) {
89                Future<Boolean> rv = null;
90                while(rv == null) {
91                        try {
92                                rv = client.set(k, expiration, value);
93                        } catch(IllegalStateException ex) {
94                                // Need to slow down a bit when we start getting rejections.
95                                try {
96                                        if(rv != null) {
97                                                rv.get(250, TimeUnit.MILLISECONDS);
98                                        } else {
99                                                Thread.sleep(250);
100                                        }
101                                } catch(InterruptedException ie) {
102                                        Thread.currentThread().interrupt();
103                                } catch(Exception e2) {
104                                        // Ignore exceptions here.  We're just trying to slow
105                                        // down input.
106                                }
107                        }
108 
109                }
110                return rv;
111        }
112 
113        private void watch(final String key, final Future<Boolean> f) {
114                if(executorService != null && storageListener != null) {
115                        executorService.execute(new Runnable() {
116                                public void run() {
117                                        try {
118                                                storageListener.storeResult(key, f.get());
119                                        } catch(Exception e) {
120                                                storageListener.errorStoring(key, e);
121                                        }
122                                }
123                        });
124                }
125        }
126 
127        /**
128         * If you are interested in the results of your data load, this interface
129         * will receive them.
130         */
131        public interface StorageListener {
132 
133                /**
134                 * Normal path response for a set.
135                 *
136                 * @param k the key that was being set
137                 * @param result true if the set changed the DB value
138                 */
139                void storeResult(String k, boolean result);
140 
141                /**
142                 * @param k the key that was attempting to be stored
143                 * @param e the error received while storing that key
144                 */
145                void errorStoring(String k, Exception e);
146        }
147}

[all classes][net.spy.memcached.util]
EMMA 2.0.5312 (C) Vladimir Roubtsov