mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user