Merge remote-tracking branch 'origin/master'

This commit is contained in:
Rob Austin
2015-04-23 12:25:09 +01:00
2 changed files with 107 additions and 14 deletions
@@ -1,5 +1,6 @@
package net.openhft.chronicle.map;
import com.sun.nio.file.SensitivityWatchEventModifier;
import net.openhft.chronicle.hash.function.SerializableFunction;
import org.jetbrains.annotations.NotNull;
@@ -7,6 +8,7 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -18,15 +20,97 @@ import java.util.stream.Stream;
public class FilePerKeyMap<K, V> implements ChronicleMap<K, V> {
private String dir;
private Path dirPath;
private Map<File, Long> lastModifiedByProgram = new ConcurrentHashMap<>();
public FilePerKeyMap(String dir) {
try {
this.dir = dir;
dirPath = Paths.get(dir);
Files.createDirectories(dirPath);
new Thread("WatcherThread") {
public void run() {
try {
WatchService watcher = FileSystems.getDefault().newWatchService();
dirPath.register(watcher, new WatchEvent.Kind[]{
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY},
SensitivityWatchEventModifier.HIGH
);
while(true){
WatchKey key = null;
try {
key = watcher.take();
System.out.println("Event Taken");
for (WatchEvent<?> event : key.pollEvents()) {
// get event type
WatchEvent.Kind<?> kind = event.kind();
// get file name
@SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path fileName = ev.context();
String mapKey = fileName.toString();
if (kind == StandardWatchEventKinds.OVERFLOW) {
System.out.println("OVERFLOW");
continue;
} else if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
Path p = dirPath.resolve(fileName);
String mapVal = getFileContents(p);
if(isProgrammaticUpdate(p.toFile())){
System.out.println("Programmatic create to " + mapKey + " : " + mapVal);
}else {
System.out.println("created " + mapKey + " : " + mapVal);
}
} else if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
Path p = dirPath.resolve(fileName);
if(isProgrammaticUpdate(p.toFile())){
System.out.println("Programmatic delete to " + mapKey);
lastModifiedByProgram.remove(p.toFile());
}else {
System.out.println("User delete " + mapKey);
}
} else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) {
Path p = dirPath.resolve(fileName);
String mapVal = getFileContents(p);
if(isProgrammaticUpdate(p.toFile())){
System.out.println("Programmatic update to " + mapKey + " : " + mapVal);
}else {
System.out.println("User modified " + mapKey + " : " + mapVal);
}
}
}
} catch (InterruptedException e) {
System.out.println("Watcher service exiting");
return;
}finally{
key.reset();
}
}
} catch (IOException e) {
throw new AssertionError(e);
}
}
}.start();
} catch (IOException e) {
throw new AssertionError(e);
}
this.dir = dir;
}
private boolean isProgrammaticUpdate(File file){
if(lastModifiedByProgram.containsKey(file)){
return file.lastModified() == lastModifiedByProgram.get(file) ? true : false;
}else{
return false;
}
}
@Override
@@ -241,6 +325,7 @@ public class FilePerKeyMap<K, V> implements ChronicleMap<K, V> {
Files.write(path, value.getBytes(), StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE);
lastModifiedByProgram.put(path.toFile(), path.toFile().lastModified());
} catch (IOException e) {
throw new AssertionError(e);
}
@@ -249,6 +334,7 @@ public class FilePerKeyMap<K, V> implements ChronicleMap<K, V> {
private void deleteFile(Path path){
try {
Files.delete(path);
lastModifiedByProgram.put(path.toFile(), path.toFile().lastModified());
} catch (IOException e) {
throw new AssertionError(e);
}
@@ -23,12 +23,13 @@ public class FilePerMapKeyTest {
}
/**
* Testing the put
* Testing all the methods of the map with simple tests.
*/
@Test
public void testPut(){
public void testMapMethods() {
//There are no entries in the map so null should be returned
FilePerKeyMap<String, String> map = new FilePerKeyMap<>("/tmp/filepermaptests");
//just in case it hasn't been cleared up last time
map.clear();
@@ -64,7 +65,6 @@ public class FilePerMapKeyTest {
map.put("one", "test1");
map.put("two", "test2");
map.put("three", "test3");
assertEquals(3, map.size());
val = map.remove("two");
@@ -90,26 +90,33 @@ public class FilePerMapKeyTest {
assertTrue(set.contains("six"));
assertTrue(set.contains("seven"));
set = (Set)map.values();
set = (Set) map.values();
assertEquals(3, set.size());
assertTrue(set.contains("test5"));
assertTrue(set.contains("test6"));
assertTrue(set.contains("test7"));
Set<Map.Entry> entryset = (Set)map.entrySet();
Set<Map.Entry> entryset = (Set) map.entrySet();
assertEquals(3, entryset.size());
for(Iterator<Map.Entry> it = entryset.iterator(); it.hasNext();){
for (Iterator<Map.Entry> it = entryset.iterator(); it.hasNext(); ) {
Map.Entry entry = it.next();
if(entry.getKey().equals("five")){
assertEquals(entry.getValue(),"test5");
}else if(entry.getKey().equals("six")){
assertEquals(entry.getValue(),"test6");
}else if(entry.getKey().equals("seven")){
assertEquals(entry.getValue(),"test7");
}else{
if (entry.getKey().equals("five")) {
assertEquals(entry.getValue(), "test5");
} else if (entry.getKey().equals("six")) {
assertEquals(entry.getValue(), "test6");
} else if (entry.getKey().equals("seven")) {
assertEquals(entry.getValue(), "test7");
} else {
//should never get here!!
assertTrue(false);
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}