From f77c31d703c99883849c3a9b66dd321378b6749c Mon Sep 17 00:00:00 2001 From: danielshaya Date: Wed, 22 Apr 2015 19:36:12 +0100 Subject: [PATCH 1/2] Initial commit for FilePerMap implementation. --- .../openhft/chronicle/map/FilePerKeyMap.java | 62 ++++++++++++++++++- .../chronicle/map/FilePerMapKeyTest.java | 31 ++++++---- 2 files changed, 80 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java b/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java index 21039e287..87f74cb44 100644 --- a/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java +++ b/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java @@ -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; @@ -21,12 +22,71 @@ public class FilePerKeyMap implements ChronicleMap { 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 ev = (WatchEvent) 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); + System.out.println("created " + mapKey + " : " + mapVal); + } else if (kind == StandardWatchEventKinds.ENTRY_DELETE) { + System.out.println("deleted " + mapKey); + } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { + Path p = dirPath.resolve(fileName); + String mapVal = getFileContents(p); + System.out.println("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; } @Override diff --git a/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java b/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java index 7f0500255..f141d8dde 100644 --- a/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java +++ b/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java @@ -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 map = new FilePerKeyMap<>("/tmp/filepermaptests"); + //just in case it hasn't been cleared up last time map.clear(); @@ -90,26 +91,32 @@ 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 entryset = (Set)map.entrySet(); + Set entryset = (Set) map.entrySet(); assertEquals(3, entryset.size()); - for(Iterator it = entryset.iterator(); it.hasNext();){ + for (Iterator 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(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } } + } From 772ad8f7c8c828894d9ba3a6f07c55c3982aab94 Mon Sep 17 00:00:00 2001 From: danielshaya Date: Thu, 23 Apr 2015 11:45:52 +0100 Subject: [PATCH 2/2] Initial commit for FilePerMap implementation. --- .../openhft/chronicle/map/FilePerKeyMap.java | 32 +++++++++++++++++-- .../chronicle/map/FilePerMapKeyTest.java | 6 ++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java b/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java index 87f74cb44..67cb456d2 100644 --- a/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java +++ b/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java @@ -8,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; @@ -19,6 +20,7 @@ import java.util.stream.Stream; public class FilePerKeyMap implements ChronicleMap { private String dir; private Path dirPath; + private Map lastModifiedByProgram = new ConcurrentHashMap<>(); public FilePerKeyMap(String dir) { try { @@ -60,13 +62,27 @@ public class FilePerKeyMap implements ChronicleMap { } else if (kind == StandardWatchEventKinds.ENTRY_CREATE) { Path p = dirPath.resolve(fileName); String mapVal = getFileContents(p); - System.out.println("created " + mapKey + " : " + mapVal); + 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) { - System.out.println("deleted " + mapKey); + 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); - System.out.println("modified " + mapKey + " : " + mapVal); + if(isProgrammaticUpdate(p.toFile())){ + System.out.println("Programmatic update to " + mapKey + " : " + mapVal); + }else { + System.out.println("User modified " + mapKey + " : " + mapVal); + } } } @@ -89,6 +105,14 @@ public class FilePerKeyMap implements ChronicleMap { } } + private boolean isProgrammaticUpdate(File file){ + if(lastModifiedByProgram.containsKey(file)){ + return file.lastModified() == lastModifiedByProgram.get(file) ? true : false; + }else{ + return false; + } + } + @Override public int size() { return (int)getFiles(dirPath).count(); @@ -301,6 +325,7 @@ public class FilePerKeyMap implements ChronicleMap { 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); } @@ -309,6 +334,7 @@ public class FilePerKeyMap implements ChronicleMap { private void deleteFile(Path path){ try { Files.delete(path); + lastModifiedByProgram.put(path.toFile(), path.toFile().lastModified()); } catch (IOException e) { throw new AssertionError(e); } diff --git a/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java b/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java index f141d8dde..5e7228d3b 100644 --- a/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java +++ b/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java @@ -65,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"); @@ -112,10 +111,11 @@ public class FilePerMapKeyTest { assertTrue(false); } } + try { - Thread.sleep(2000); + Thread.sleep(3000); } catch (InterruptedException e) { - e.printStackTrace(); + e.printStackTrace(); } }