Skip to content

Commit eb6cec0

Browse files
committed
first test run with chunk cache.
1 parent 248a922 commit eb6cec0

File tree

8 files changed

+186
-69
lines changed

8 files changed

+186
-69
lines changed

src/net/sharksystem/aasp/AASPChunkCache.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,11 @@ public interface AASPChunkCache {
3434

3535
/**
3636
*
37-
* @param chronologically in chronological order: true: oldest message comes
3837
* first, false: newest message comes first
3938
* @return iterator of all messages in that chunk cache
4039
* @throws IOException
4140
*/
42-
Iterator<CharSequence> getMessages(boolean chronologically) throws IOException;
41+
Iterator<CharSequence> getMessages() throws IOException;
4342

4443
/**
4544
* Returns a message with a given position

src/net/sharksystem/aasp/AASPChunkStorageFS.java

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ String getFullFileName(int era, String targetUrl) {
6464
/**
6565
*
6666
* @param era
67-
* @param fileName
6867
* @return full name (path/name) of that given url and target. Directories
6968
* are expected to be existent
7069
*/
@@ -110,45 +109,10 @@ public boolean accept(File dir, String fileName) {
110109
@Override
111110
public void dropChunks(int era) throws IOException {
112111
// here comes a Java 6 compatible version - fits to android SDK 23
113-
String eraPathName = this.rootDirectory + "/" + Integer.toString(era);
114-
File dir = new File(eraPathName);
115-
116-
String[] dirEntries = dir.list();
117-
118-
/*
119-
Path dir = Paths.get(this.rootDirectory + "/" + Integer.toString(era));
120-
121-
DirectoryStream<Path> entries = null;
122-
try {
123-
entries = Files.newDirectoryStream(dir);
124-
}
125-
catch(IOException ioe) {
126-
// directory does not exist - ok, nothing to drop
127-
return;
128-
}
129-
130-
for (Path path : entries) {
131-
File file = path.toFile();
132-
file.delete();
133-
}
134-
*/
135-
if(dirEntries != null) {
136-
for(String fileName : dirEntries) {
137-
File fileInDir = new File(eraPathName + "/" + fileName);
138-
try {
139-
fileInDir.delete();
140-
}
141-
catch(RuntimeException e) {
142-
System.err.println("AASPStorageFS: cannot remove old file:" + e.getLocalizedMessage());
143-
// try next
144-
}
145-
}
146-
}
147-
148-
// finally remove directory itself
149-
// dir.toFile().delete();
112+
String eraPathName = this.rootDirectory + "/" + Integer.toString(era);
113+
114+
AASPEngineFS.removeFolder(eraPathName);
150115

151-
dir.delete();
152116
}
153117

154118
String getRootPath() {

src/net/sharksystem/aasp/AASPEngineFS.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,33 @@ public AASPChunkStorage getReceivedChunkStorage(CharSequence sender) {
9898
String dir = this.rootDirectory + "/" + sender;
9999
return new AASPChunkStorageFS(dir);
100100
}
101+
102+
////////////////////////////////////////////////////////////////////////////////////////
103+
// helper //
104+
////////////////////////////////////////////////////////////////////////////////////////
105+
106+
static void removeFolder(String eraPathName) {
107+
File dir = new File(eraPathName);
108+
109+
String[] dirEntries = dir.list();
110+
111+
if(dirEntries != null) {
112+
for(String fileName : dirEntries) {
113+
File fileInDir = new File(eraPathName + "/" + fileName);
114+
if(fileInDir.isDirectory()) {
115+
AASPEngineFS.removeFolder(fileInDir.getAbsolutePath());
116+
} else {
117+
try {
118+
fileInDir.delete();
119+
} catch (RuntimeException e) {
120+
System.err.println("AASPEngineFS: cannot file:" + e.getLocalizedMessage());
121+
// try next
122+
}
123+
}
124+
}
125+
}
126+
127+
dir.delete();
128+
}
129+
101130
}

src/net/sharksystem/aasp/AASPInMemoChunkCache.java

100755100644
Lines changed: 122 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
import java.util.ArrayList;
55
import java.util.Iterator;
66
import java.util.List;
7+
import java.util.NoSuchElementException;
78

89
/**
910
*
1011
* @author thsc
1112
*/
1213
class AASPInMemoChunkCache implements AASPChunkCache {
14+
public static final int DEFAULT_MAX_CACHE_SIZE = 1000;
1315
private final CharSequence uri;
1416
private final AASPChunkStorageFS chunkStorage;
1517
private final int fromEra;
@@ -21,19 +23,26 @@ class AASPInMemoChunkCache implements AASPChunkCache {
2123
private List<CharSequence> messageCache;
2224
private int firstIndexMessageCache = -1;
2325
private int lastIndexMessageCache = -1;
24-
private int maxCacheLen = 1000;
26+
private int maxCacheLen;
2527

2628
private int numberOfMessages = 0;
2729

28-
public AASPInMemoChunkCache(AASPChunkStorageFS chunkStorage,
29-
CharSequence uri, int fromEra, int toEra) {
30-
30+
public AASPInMemoChunkCache(AASPChunkStorageFS chunkStorage,
31+
CharSequence uri, int fromEra, int toEra, int maxCacheLen) {
32+
3133
this.uri = uri;
3234
this.chunkStorage = chunkStorage;
3335
this.fromEra = fromEra;
3436
this.toEra = toEra;
37+
this.maxCacheLen = maxCacheLen;
3538
}
36-
39+
40+
public AASPInMemoChunkCache(AASPChunkStorageFS chunkStorage,
41+
CharSequence uri, int fromEra, int toEra) {
42+
43+
this(chunkStorage, uri, fromEra, toEra, DEFAULT_MAX_CACHE_SIZE);
44+
}
45+
3746
private boolean initialized = false;
3847

3948
private void initialize() throws IOException {
@@ -87,15 +96,10 @@ public CharSequence getURI() {
8796
}
8897

8998
@Override
90-
public Iterator<CharSequence> getMessages(boolean chronologically) throws IOException {
99+
public Iterator<CharSequence> getMessages() throws IOException {
91100
this.initialize();
92101

93-
List<CharSequence> dummyList = new ArrayList<>();
94-
95-
dummyList.add("dummy entry 1");
96-
dummyList.add("dummy entry 2");
97-
98-
return dummyList.iterator();
102+
return new ChunkListMessageIterator(this.chunkList);
99103
}
100104

101105
@Override
@@ -104,7 +108,7 @@ public CharSequence getMessage(int position, boolean chronologically)
104108

105109
this.initialize();
106110

107-
if(position > this.numberOfMessages)
111+
if(position >= this.numberOfMessages)
108112
throw new AASPException("Position exceeds number of message");
109113

110114
if(!chronologically) {
@@ -125,14 +129,15 @@ public CharSequence getMessage(int position, boolean chronologically)
125129
int fittingChunkIndex = 0;
126130

127131
for(AASPChunk chunk : this.chunkList) {
128-
lastIndex = firstIndex + chunk.getNumberMessage();
132+
lastIndex = firstIndex + chunk.getNumberMessage() - 1;
129133

130134
if(position >= firstIndex && position <= lastIndex) {
131135
// we have got our chunk
132136
fittingChunk = chunk;
133137
break;
134138
}
135139

140+
firstIndex += chunk.getNumberMessage();
136141
fittingChunkIndex++;
137142
}
138143

@@ -145,8 +150,39 @@ public CharSequence getMessage(int position, boolean chronologically)
145150
// reset cache
146151
this.messageCache = new ArrayList<>();
147152

153+
/////////////////////////////////////////////////////////////////
148154
// simple approach in that first implementation ... we keep fitting chunk in memory
155+
/////////////////////////////////////////////////////////////////
156+
149157
Iterator<CharSequence> messages = fittingChunk.getMessages();
158+
159+
// chunk bigger than max cache size?
160+
int chunkSize = fittingChunk.getNumberMessage();
161+
if(chunkSize > this.maxCacheLen) {
162+
// calculate how many messages to skip before caching
163+
164+
/*
165+
situation:
166+
chunk head |................position...........................| tail
167+
cache head |................| tail
168+
169+
solution: put position in middle of the cache
170+
chunk |................position...........................|
171+
planned cache |........position........|
172+
skipLen...|
173+
*/
174+
175+
int skipLen = position - (this.maxCacheLen / 2);
176+
177+
// first index in cache will be this one:
178+
firstIndex += skipLen;
179+
180+
// skip
181+
for(;skipLen > 0; skipLen--) {
182+
this.messageCache.add(messages.next());
183+
}
184+
}
185+
150186
this.firstIndexMessageCache = firstIndex;
151187

152188
int counter = 0;
@@ -159,13 +195,83 @@ public CharSequence getMessage(int position, boolean chronologically)
159195
this.lastIndexMessageCache = this.firstIndexMessageCache + counter - 1;
160196

161197
// cache filled - call again
162-
return this.getMessage(position, chronologically);
198+
/* not: it is always chronologically true!!
199+
a) we already came in with true -> it remains true
200+
b) we came with false -> we have already recalculated that position, we would
201+
move it around again with that call - keep position unchanged: true!
202+
*/
203+
204+
return this.getMessage(position, true);
163205
}
164206

165207
@Override
166208
public void add(CharSequence message) throws IOException {
167209
// TODO
168210
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
169211
}
170-
}
171212

213+
private class ChunkListMessageIterator implements Iterator<CharSequence> {
214+
215+
private final List<AASPChunk> chunkList;
216+
private AASPChunk currentChunk;
217+
private int nextIndex;
218+
private Iterator<CharSequence> currentIterator;
219+
private CharSequence messageAhead;
220+
221+
public ChunkListMessageIterator(List<AASPChunk> chunkList) throws IOException {
222+
this.chunkList = chunkList;
223+
this.currentChunk = null;
224+
this.nextIndex = 0;
225+
this.messageAhead = null; // mark as empty
226+
this.readAhead(); // init cache
227+
}
228+
229+
/**
230+
* read next message in field messageAhead.
231+
*/
232+
private void readAhead() {
233+
if (this.currentIterator != null) {
234+
if (this.currentIterator.hasNext()) {
235+
// 'normal' case: we read next message
236+
this.messageAhead = this.currentIterator.next();
237+
return; // done
238+
}
239+
}
240+
// no more messages in that iterator / chunk
241+
if (this.chunkList == null || nextIndex >= this.chunkList.size() ) {
242+
return; // there is no list at all or we are already through with it
243+
}
244+
245+
// open next chunk / iterator
246+
this.currentChunk = this.chunkList.get(this.nextIndex++);
247+
try {
248+
this.currentIterator = this.currentChunk.getMessages();
249+
this.readAhead(); // next try
250+
} catch (IOException e) {
251+
// cannot recover from that problem
252+
return;
253+
}
254+
}
255+
256+
@Override
257+
public boolean hasNext() {
258+
return this.messageAhead != null;
259+
}
260+
261+
@Override
262+
public CharSequence next() {
263+
if(this.messageAhead == null) {
264+
throw new NoSuchElementException("list empty or already reached end");
265+
}
266+
267+
// remove that single message cache
268+
CharSequence retMessage = this.messageAhead;
269+
this.messageAhead = null;
270+
271+
// read ahead - if possible
272+
this.readAhead();
273+
274+
return retMessage;
275+
}
276+
}
277+
}

test/net/sharksystem/aasp/AASPChunkReceiverTester.java

100755100644
File mode changed.

test/net/sharksystem/aasp/AASPEngineThread.java

100755100644
File mode changed.

test/net/sharksystem/aasp/BasicTests.java

100755100644
File mode changed.

0 commit comments

Comments
 (0)