EMMA Coverage Report (generated Tue Apr 17 08:51:20 BST 2007)
[all classes][org.jtoolkit.essence.data.impl]

COVERAGE SUMMARY FOR SOURCE FILE [DatableStore.java]

nameclass, %method, %block, %line, %
DatableStore.java100% (1/1)100% (7/7)78%  (244/311)89%  (56.1/63)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DatableStore100% (1/1)100% (7/7)78%  (244/311)89%  (56.1/63)
notifyUpdate (Object, Object): void 100% (1/1)60%  (9/15)89%  (3.6/4)
flush (): void 100% (1/1)74%  (64/87)80%  (14.4/18)
DatableStore (String, Store$CollectionType, DataValueClass, DataValueClass, S... 100% (1/1)77%  (128/166)89%  (22.2/25)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
clear (): void 100% (1/1)100% (11/11)100% (5/5)
close (): void 100% (1/1)100% (19/19)100% (7/7)
run (): void 100% (1/1)100% (9/9)100% (3/3)

1package org.jtoolkit.essence.data.impl;
2 
3import org.apache.commons.logging.Log;
4import static org.apache.commons.logging.LogFactory.getLog;
5import org.jetbrains.annotations.NotNull;
6import org.jetbrains.annotations.Nullable;
7import static org.jtoolkit.essence.app.pojo.DatableUtils.readObjects;
8import static org.jtoolkit.essence.app.pojo.DatableUtils.writeObjects;
9import org.jtoolkit.essence.app.pojo.impl.DataValueClass;
10import org.jtoolkit.essence.concurrency.Concurrency;
11import org.jtoolkit.essence.concurrency.ThreadSafe;
12import org.jtoolkit.essence.concurrency.Threads;
13import org.jtoolkit.essence.utils.IOUtils;
14import static org.jtoolkit.essence.utils.IOUtils.getInputStream;
15import org.jtoolkit.essence.utils.impl.MapArray;
16 
17import java.io.*;
18import java.util.Map;
19import java.util.concurrent.ScheduledFuture;
20import java.util.concurrent.TimeUnit;
21/*
22   Copyright 2006 Peter Lawrey
23 
24   Licensed under the Apache License, Version 2.0 (the "License");
25   you may not use this file except in compliance with the License.
26   You may obtain a copy of the License at
27 
28       http://www.apache.org/licenses/LICENSE-2.0
29 
30   Unless required by applicable law or agreed to in writing, software
31   distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
32   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33   See the License for the specific language governing permissions and
34   limitations under the License.
35*/
36 
37/**
38 * @author Peter Lawrey
39 */
40@ThreadSafe(Concurrency.CONCURRENT_READ_WRITE)
41public class DatableStore<K, V> extends MemoryStore<K, V> implements Runnable {
42    private static final Log LOG = getLog(DatableStore.class);
43    private static final long PERIOD = 5 * 1000;
44    private final String filename;
45    private final ScheduledFuture updateTask;
46    private final Object diskLock = new Object();
47    private static final String KEY_VALUE_PAIRS = "Key/Value Pairs";
48 
49    @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"})
50    private boolean dirty = false;
51 
52    public DatableStore(String name, CollectionType collectionType, DataValueClass<K> keyClass, DataValueClass<V> valueClass, String filename) throws IOException {
53        super(name, collectionType, keyClass, valueClass, ReadMode.ALL, PersistMode.ASYNC);
54        this.filename = filename;
55        DataInputStream in = null;
56        try {
57            in = new DataInputStream(getInputStream(filename));
58            try {
59                String fileFormat = in.readUTF();
60                if (!fileFormat.equals(KEY_VALUE_PAIRS))
61                    throw new UnsupportedEncodingException("Unable to read file " + filename + ", format not supported " + fileFormat);
62            } catch (IOException ignored) {
63                throw new UnsupportedEncodingException("Unable to read file " + filename + ", unknown format not supported");
64            }
65 
66            for (Map.Entry<K, V> entry : MapArray.<K, V>toMap(readObjects(in, 0, Integer.MAX_VALUE)).entrySet()) {
67                if (LOG.isDebugEnabled()) LOG.debug(name + ": " + entry.getKey() + "= " + entry.getValue());
68                doPut(entry.getKey(), entry.getValue(), true, true);
69            }
70        } catch (FileNotFoundException e) {
71            if (LOG.isInfoEnabled()) LOG.info(name + ": Datable file not found, creating " + e);
72            dirty = true;
73        } finally {
74            IOUtils.close(in);
75        }
76        long period;
77        if (persistMode == PersistMode.SEMI_SYNC)
78            period = PERIOD / 20;
79        else
80            period = PERIOD;
81        updateTask = canWrite() ?
82                getStoreMonitor().scheduleAtFixedRate(Threads.getWeakRunnable(this), period, period, TimeUnit.MILLISECONDS) : null;
83    }
84 
85    protected void clear() {
86        super.clear();
87        if (canWrite())  {
88            dirty = true;
89            flush();
90        }
91    }
92 
93    public void close() {
94        super.close();
95        if (canWrite()) {
96            updateTask.cancel(false);
97            if (dirty)
98                flush();
99            dirty = false;
100        }
101    }
102 
103    protected void notifyUpdate(@NotNull K key, @Nullable V newValue) {
104        try {
105            super.notifyUpdate(key, newValue);
106        } finally {
107            dirty = true;
108        }
109    }
110 
111    public void run() {
112        if (canWrite() && dirty)
113            flush();
114    }
115 
116    private void flush() {
117        DataOutputStream out = null;
118        try {
119            synchronized (diskLock) {
120                dirty = false;
121                File file = new File(filename);
122                IOUtils.deleteIfTmp(file);
123 
124                File file2 = IOUtils.getNewFile(filename);
125                out = new DataOutputStream(IOUtils.getOutputStream(file2));
126                out.writeUTF(KEY_VALUE_PAIRS);
127                // take a synchronised copy of this.
128                Map<K, V> map = asMap();
129                writeObjects(out, MapArray.asArray(map));
130                IOUtils.close(out);
131                
132                dirty = !IOUtils.rename(file, file2);
133            }
134        } catch (IOException e) {
135            LOG.error(Thread.currentThread().getName() + ": Unable to save " + filename + " cannot create.", e);
136        } finally {
137            IOUtils.close(out);
138        }
139    }
140}

[all classes][org.jtoolkit.essence.data.impl]
EMMA 2.0.5312 (C) Vladimir Roubtsov