Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Improved content caching mechanism. Bugfixes related to it. #10

Merged
merged 1 commit into from

2 participants

@ovidiuiliescu
Collaborator

No description provided.

@robert-virkus robert-virkus merged commit 9258ea6 into Enough-Software:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 27, 2012
This page is out of date. Refresh to see the latest.
View
3  enough-polish-j2me/source/src/de/enough/polish/content/ContentDescriptor.java
@@ -16,6 +16,9 @@
*
*/
public class ContentDescriptor implements Externalizable {
+
+ public static int PRIORITY_CRITICAL = Integer.MAX_VALUE;
+
/**
* the default version
*/
View
8 enough-polish-j2me/source/src/de/enough/polish/content/filter/impl/HttpContentFilter.java
@@ -3,8 +3,16 @@
import de.enough.polish.content.ContentDescriptor;
import de.enough.polish.content.filter.ContentFilter;
+/**
+ * Filter for HTTP content
+ * @author Ovidiu Iliescu
+ *
+ */
public class HttpContentFilter implements ContentFilter {
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.filter.ContentFilter#filter(de.enough.polish.content.ContentDescriptor)
+ */
public boolean filter(ContentDescriptor descriptor) {
return descriptor.getUrl().startsWith("http://");
}
View
8 ...gh-polish-j2me/source/src/de/enough/polish/content/filter/impl/ResourceContentFilter.java
@@ -3,8 +3,16 @@
import de.enough.polish.content.ContentDescriptor;
import de.enough.polish.content.filter.ContentFilter;
+/**
+ * Filter for Resource content
+ * @author Ovidiu Iliescu
+ *
+ */
public class ResourceContentFilter implements ContentFilter {
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.filter.ContentFilter#filter(de.enough.polish.content.ContentDescriptor)
+ */
public boolean filter(ContentDescriptor descriptor) {
return descriptor.getUrl().startsWith("resources://");
}
View
133 enough-polish-j2me/source/src/de/enough/polish/content/source/ContentSource.java
@@ -112,7 +112,7 @@ public void attachSource(ContentSource source) {
this.sources.add(source);
//#debug debug
- info("attached source : " + source);
+ System.out.println(this.id + " : " + "attached source : " + source);
}
/**
@@ -139,42 +139,64 @@ public void detachSource(ContentSource source) {
this.sources.remove(source);
//#debug debug
- info("detached source : " + source);
+ System.out.println(this.id + " : " + "detached source : " + source);
}
+ /**
+ * Sets the content filter
+ * @param filter the filter to set
+ */
public void setContentFilter(ContentFilter filter) {
this.filter = filter;
//#debug debug
- info("set filter : " + filter);
+ System.out.println(this.id + " : " + "set filter : " + filter);
}
+ /**
+ * Returns the content filter
+ * @return the filter
+ */
public ContentFilter getFilter() {
return this.filter;
}
+ /**
+ * Adds a content transformation
+ * @param transformer the transformation
+ */
public void addContentTransform(ContentTransform transformer) {
String id = transformer.getTransformId();
if (!id.equals(ContentDescriptor.TRANSFORM_NONE)
&& this.transformers.containsKey(id)) {
//#debug info
- info("overwriting transformer with id \"" + id + "\"");
+ System.out.println(this.id + " : " + "overwriting transformer with id \"" + id + "\"");
}
this.transformers.put(id, transformer);
//#debug debug
- info("added transform : " + transformer);
+ System.out.println(this.id + " : " + "added transform : " + transformer);
}
+ /**
+ * Removes a content transformation
+ * @param transformer the transformation
+ */
public void removeContentTransform(ContentTransform transformer) {
String id = transformer.getTransformId();
this.transformers.remove(id);
//#debug debug
- info("removed transform : " + transformers);
+ System.out.println(this.id + " : " + "removed transform : " + transformers);
}
+ /**
+ * Loads content from all underlying sources
+ * @param descriptor the content descriptor to load
+ * @return the content Object
+ * @throws ContentException
+ */
public Object loadContent(ContentDescriptor descriptor)
throws ContentException {
Object data = loadContentData(descriptor);
@@ -188,25 +210,25 @@ public Object loadContent(ContentDescriptor descriptor)
ContentFilter filter = source.getFilter();
if (filter != null && !filter.filter(descriptor)) {
//#debug debug
- info("filtered source : " + source);
+ System.out.println(this.id + " : " + "filtered source : " + source);
continue;
}
//#debug debug
- info("load content : " + descriptor + " : with source : "
+ System.out.println(this.id + " : " + "load content : " + descriptor + " : with source : "
+ source);
data = source.loadContent(descriptor);
if (data != null) {
data = transformContent(descriptor, data);
//#debug debug
- info("transformed content : " + data);
+ System.out.println(this.id + " : " + "transformed content : " + data);
if(descriptor.getCachingPolicy() == ContentDescriptor.CACHING_READ_WRITE) {
storeContent(descriptor, data);
} else {
//#debug debug
- info("no storage due to caching policy");
+ System.out.println(this.id + " : " + "no storage due to caching policy");
}
return data;
}
@@ -225,6 +247,12 @@ public Object loadContent(ContentDescriptor descriptor)
return data;
}
+ /**
+ * Transforms content with a transformation
+ * @param descriptor the content descriptor containing the transformation
+ * @param data the data to transform
+ * @return
+ */
protected Object transformContent(ContentDescriptor descriptor, Object data) {
if (this.transformers.size() > 0
&& descriptor.getTransformID() != ContentDescriptor.TRANSFORM_NONE
@@ -234,12 +262,12 @@ protected Object transformContent(ContentDescriptor descriptor, Object data) {
if (transformer != null) {
try {
//#debug debug
- info("using transform : " + transformer
+ System.out.println(this.id + " : " + "using transform : " + transformer
+ " : for descriptor : " + descriptor);
data = transformer.transformContent(data);
} catch (IOException e) {
//#debug error
- System.out.println("error transforming " + descriptor + ":"
+ System.out.println(this.id + " : " + "error transforming " + descriptor + ":"
+ e);
}
@@ -250,19 +278,25 @@ protected Object transformContent(ContentDescriptor descriptor, Object data) {
return data;
}
+ /**
+ * Loads content data from this content source or from storage
+ * @param descriptor the descriptor to load the content data for
+ * @return the content data
+ * @throws ContentException
+ */
protected Object loadContentData(ContentDescriptor descriptor)
throws ContentException {
// if this source has a storage ...
if (hasStorage()) {
//#debug debug
- info("has storage");
+ System.out.println(this.id + " : " + "has storage");
// prepare the storage if it isn't
if (!this.storageIndex.isPrepared()) {
this.storageIndex.prepare();
//#debug debug
- info("storage index prepared");
+ System.out.println(this.id + " : " + "storage index prepared");
}
// get the StorageReference to a potentially stored content
@@ -272,7 +306,7 @@ protected Object loadContentData(ContentDescriptor descriptor)
// if the content is stored ...
if (reference != null) {
//#debug debug
- info("found reference : " + reference);
+ System.out.println(this.id + " : " + "found reference : " + reference);
// update its activity
reference.updateActivity();
@@ -324,12 +358,12 @@ protected Object loadContent(ContentDescriptor descriptor,
try {
if (reference != null) {
//#debug debug
- info("loading content from storage : " + reference);
+ System.out.println(this.id + " : " + "loading content from storage : " + reference);
return load(reference);
} else {
//#debug debug
- info("loading content from source : " + descriptor);
+ System.out.println(this.id + " : " + "loading content from source : " + descriptor);
return load(descriptor);
}
} catch (IOException e) {
@@ -345,7 +379,7 @@ protected Object loadContent(ContentDescriptor descriptor,
* @param data the data that needs to be stored
* @return an Object [], the first element is an Integer object containing the stored object's data size, the second element is a reference to the stored object
*/
- protected abstract Object[] storeContentAndGetDataSize(ContentDescriptor descriptor, Object data) throws IOException ;
+ protected abstract Object[] storeContentAndGetDataSize(ContentDescriptor descriptor, Object data) throws IOException, ContentException ;
protected void storeContent(ContentDescriptor descriptor, Object data)
throws ContentException {
@@ -354,7 +388,7 @@ protected void storeContent(ContentDescriptor descriptor, Object data)
// if this ContentSource has a storage ...
if (hasStorage()) {
//#debug debug
- info("storing content : " + data + " : for :" + descriptor);
+ System.out.println(this.id + " : " + "storing content : " + data + " : for :" + descriptor);
int size;
Object reference;
@@ -368,18 +402,23 @@ protected void storeContent(ContentDescriptor descriptor, Object data)
size = getSize(descriptor, data);
//#debug debug
- info("data size for : " + data + " : " + size);
+ System.out.println(this.id + " : " + "data size for : " + data + " : " + size);
// store the content
reference = store(descriptor, data);
}
- // add the reference to the StorageIndex
- this.storageIndex.addReference(new StorageReference(descriptor,
- size, reference));
+ // add the reference to the StorageIndex, if storage was successful
+ if ( reference != null ) {
+ this.storageIndex.addReference(new StorageReference(descriptor,
+ size, reference));
- //#debug debug
- info("content stored with reference : " + reference);
+ //#debug debug
+ System.out.println(this.id + " : " + "content stored with reference : " + reference);
+ } else {
+ //#debug debug
+ System.out.println(this.id + " : " + "content deliberately not stored");
+ }
}
} catch (IOException e) {
String message = "error storing content : " + e;
@@ -402,7 +441,7 @@ protected void destroyContent(ContentDescriptor descriptor)
// if this ContentSource has a storage ...
if (hasStorage()) {
//#debug debug
- info("destroying content : " + descriptor);
+ System.out.println(this.id + " : " + "destroying content : " + descriptor);
// get the reference to the content
StorageReference reference = this.storageIndex
@@ -422,18 +461,28 @@ protected void destroyContent(ContentDescriptor descriptor)
}
//#debug debug
- info("content destroyed : " + descriptor);
+ System.out.println(this.id + " : " + "content destroyed : " + descriptor);
}
}
-
+
/**
* If a clean is needed on the storage, the clean order is applied to the
* StorageIndex and contents are deleted until the cache size is below the
* thresholds
*/
public void clean() throws ContentException {
+ clean(0);
+ }
+
+ /**
+ * If a clean is needed on the storage in order to store an additional extraBytes number of bytes, the clean order is applied to the
+ * StorageIndex and contents are deleted until the cache size is below the
+ * thresholds
+ * @param extraBytes
+ */
+ public void clean(int extraBytes) throws ContentException {
if (hasStorage()) {
- if (!this.storageIndex.isCleanNeeded()) {
+ if (!this.storageIndex.isCleanNeeded(extraBytes)) {
return;
}
@@ -442,20 +491,29 @@ public void clean() throws ContentException {
}
//#debug debug
- info("clean : " + this.storageIndex);
+ System.out.println(this.id + " : " + "clean : " + this.storageIndex);
// apply the clean order
this.storageIndex.applyOrder();
+ boolean canDeleteFurther = true;
do {
+ // Assume that you cannot delete anything else
+ canDeleteFurther = false;
+
// get the index of the first disposable content
int index = this.storageIndex.getDisposableIndex();
// get the reference
StorageReference reference = this.storageIndex
.getReference(index);
- // destroy the content
- destroyContent(reference);
- } while ((this.storageIndex.isCleanNeeded()));
+ // destroy the content, if not critical
+ if ( reference.getPriority() != ContentDescriptor.PRIORITY_CRITICAL ) {
+ destroyContent(reference);
+
+ // Maybe we can delete other content too
+ canDeleteFurther = true;
+ }
+ } while ((this.storageIndex.isCleanNeeded(extraBytes)) && canDeleteFurther);
}
}
@@ -594,13 +652,4 @@ public String toString() {
"sources", this.sources).set("transformers", this.transformers)
.set("filter", this.filter).toString();
}
-
- /**
- * Prints an info
- *
- * @param info
- */
- public void info(String info) {
- System.out.println(this.id + " : " + info);
- }
}
View
10 enough-polish-j2me/source/src/de/enough/polish/content/source/impl/HttpContentSource.java
@@ -16,8 +16,15 @@
*/
public class HttpContentSource extends ContentSource{
+ /**
+ * The HTTP prefix
+ */
public final static String PREFIX = "http://";
+ /**
+ * Creates a new HttpContentSource
+ * @param id
+ */
public HttpContentSource(String id) {
super(id);
}
@@ -62,6 +69,9 @@ protected Object store(ContentDescriptor descriptor, Object data)
return null;
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.source.ContentSource#storeContentAndGetDataSize(de.enough.polish.content.ContentDescriptor, java.lang.Object)
+ */
protected Object[] storeContentAndGetDataSize(ContentDescriptor descriptor,
Object data) throws IOException {
// Do nothing, this is a source
View
15 ...polish-j2me/source/src/de/enough/polish/content/source/impl/PersistentContentStorage.java
@@ -17,15 +17,27 @@
import de.enough.polish.io.Serializer;
/**
+ * Defines a content storage using the Persistent Record Store mechanism on Blackberry
* @author Andre Schmidt
*
*/
public class PersistentContentStorage extends ContentSource {
+ /**
+ * The record store ID for the persistent storage
+ */
static final String STORAGE = "RMSContentStorage";
+ /**
+ * The record store instance
+ */
PersistentRecordStore store;
+ /**
+ * Creates a new PersistentContentStorage instance
+ * @param id the ID for the storage
+ * @param index the storageindex to use
+ */
public PersistentContentStorage(String id, StorageIndex index) {
super(id, index);
@@ -38,6 +50,9 @@ public PersistentContentStorage(String id, StorageIndex index) {
}
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.source.ContentSource#shutdown()
+ */
public synchronized void shutdown() {
// close the record store
try
View
26 ...h-polish-j2me/source/src/de/enough/polish/content/source/impl/PersistentStorageIndex.java
@@ -15,13 +15,36 @@
import de.enough.polish.io.Serializer;
import de.enough.polish.util.ArrayList;
+/**
+ * Defines a storage index using the Persistent Record Storage on Blackberry
+ * @author Ovidiu Iliescu
+ *
+ */
public class PersistentStorageIndex extends StorageIndex {
+ /**
+ * The record store index
+ */
static final String STORAGE = "RMSStorageIndex";
+
+ /**
+ * Indicates that the actaul record index is not known
+ */
static final int RECORD_UNKNOWN = Integer.MIN_VALUE;
+ /**
+ * The actual record store to use
+ */
PersistentRecordStore store;
+
+ /**
+ * The record ID
+ */
int recordId = RECORD_UNKNOWN;
+ /**
+ * Creates a new index, with the specified maximum size
+ * @param maxCacheSize the size of the index
+ */
public PersistentStorageIndex(int maxCacheSize) {
super(maxCacheSize);
@@ -109,6 +132,9 @@ protected void store(ArrayList index) {
}
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.storage.StorageIndex#shutdown()
+ */
public void shutdown() {
super.shutdown();
View
10 ...gh-polish-j2me/source/src/de/enough/polish/content/source/impl/ResourceContentSource.java
@@ -16,8 +16,15 @@
*/
public class ResourceContentSource extends ContentSource{
+ /**
+ * The prefix for this kind of source
+ */
public final static String PREFIX = "resource://";
+ /**
+ * Creates a new resource content source
+ * @param id the unique ID of this source
+ */
public ResourceContentSource(String id) {
super(id);
}
@@ -63,6 +70,9 @@ protected Object store(ContentDescriptor descriptor, Object data)
return null;
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.source.ContentSource#storeContentAndGetDataSize(de.enough.polish.content.ContentDescriptor, java.lang.Object)
+ */
protected Object[] storeContentAndGetDataSize(ContentDescriptor descriptor,
Object data) throws IOException {
// Do nothing, this is a source
View
127 enough-polish-j2me/source/src/de/enough/polish/content/source/impl/RmsContentStorage.java
@@ -8,35 +8,94 @@
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
+import javax.microedition.rms.RecordStoreNotOpenException;
import de.enough.polish.content.ContentDescriptor;
+import de.enough.polish.content.ContentException;
import de.enough.polish.content.source.ContentSource;
import de.enough.polish.content.storage.StorageIndex;
import de.enough.polish.content.storage.StorageReference;
import de.enough.polish.io.Serializer;
/**
+ * Defines a content storage using the RMS
* @author Andre Schmidt
*
*/
public class RmsContentStorage extends ContentSource {
- static final String STORAGE = "RMSContentStorage";
+ /**
+ * The default RMS store name
+ */
+ public static final String STORAGE = "RMSContentStorage";
+ /**
+ * The RecordStore instance to use
+ */
protected RecordStore store;
-
+
+ /**
+ * Returns the maximum total size of the store
+ * @return the maximum total size of the store
+ */
+ public static int getMaximumTotalSize() {
+ int maxSize = 0;
+ int currentSize = 0;
+ RecordStore rs = null;
+ try {
+ rs = RecordStore.openRecordStore(STORAGE, true);
+ currentSize = rs.getSize();
+ maxSize = currentSize + rs.getSizeAvailable();
+ } catch (Exception ex) {
+ // Do nothing
+ } finally {
+ try {
+ // Close record store
+ if (rs != null) {
+ rs.closeRecordStore();
+ }
+
+ // If the store is empty, delete it as well
+ if ( currentSize == 0 ) {
+ RecordStore.deleteRecordStore(STORAGE);
+ }
+ } catch (Exception ex) {
+ // Do nothing
+ }
+ }
+ return maxSize;
+ }
+
+ /**
+ * Creates a new RmsContentStor
+ * @param id
+ * @param index
+ */
public RmsContentStorage(String id, StorageIndex index) {
+ this(id, STORAGE, index);
+ }
+
+ /**
+ * Creates a new RmsContentStorage instance
+ * @param id the unique ID of this instance
+ * @param recordStoreName the name of the record store to use
+ * @param index the index to use with this content storage
+ */
+ public RmsContentStorage(String id, String recordStoreName, StorageIndex index) {
super(id, index);
// open the record store
try {
- store = RecordStore.openRecordStore(STORAGE, true);
+ store = RecordStore.openRecordStore(recordStoreName, true);
} catch (RecordStoreException e) {
//#debug error
System.out.println("unable to open record store " + e);
}
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.source.ContentSource#shutdown()
+ */
public synchronized void shutdown() {
// close the record store
try
@@ -51,12 +110,15 @@ public synchronized void shutdown() {
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.source.ContentSource#destroy(de.enough.polish.content.storage.StorageReference)
+ */
protected synchronized void destroy(final StorageReference reference) throws IOException {
try {
// get the record id
int recordId = ((Integer)reference.getReference()).intValue();
- // add the record
+ // delete the record
store.deleteRecord(recordId);
} catch (RecordStoreException e) {
@@ -67,35 +129,62 @@ protected synchronized void destroy(final StorageReference reference) throws IO
/* (non-Javadoc)
* @see de.enough.polish.content.source.ContentSource#storeContentAndGetDataSize(de.enough.polish.content.ContentDescriptor, java.lang.Object)
*/
- protected Object[] storeContentAndGetDataSize(ContentDescriptor descriptor, Object data) throws IOException {
+ protected Object[] storeContentAndGetDataSize(ContentDescriptor descriptor, Object data) throws IOException, ContentException {
+
+ // serialize the data and convert it to a byte array
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ Serializer.serialize(data, new DataOutputStream(byteStream));
+
+ // get the bytes
+ byte[] bytes = byteStream.toByteArray();
+
+ // If the data we are trying to store is bigger than the cache itself, don't even bother
+ if ( bytes.length > getStorageIndex().getAvailableCacheSize() ) {
+ return new Object[] { new Integer(bytes.length), null };
+ }
+
+ // Try to do a clean first, in case it is needed.
+ clean(bytes.length);
+
+ // add the record, if possible
+ Integer recordId = null;
try {
- // serialize the data and convert it to a byte array
- ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
- Serializer.serialize(data, new DataOutputStream(byteStream));
-
- // get the bytes
- byte[] bytes = byteStream.toByteArray();
-
- // add the record
- int recordId = store.addRecord(bytes, 0, bytes.length);
-
- return new Object[] { new Integer(bytes.length), new Integer(recordId)};
- } catch (RecordStoreException e) {
- throw new IOException("unable to store data " + e);
- }
+ if ( !this.getStorageIndex().isCleanNeeded(bytes.length) ) {
+ recordId = new Integer(store.addRecord(bytes, 0, bytes.length));
+ //#debug debug
+ System.out.println("added record for " + descriptor.getUrl());
+ } else {
+ //#debug debug
+ System.out.println("not enough space to add record for " + descriptor.getUrl());
+ }
+ } catch (Exception e) {
+ //#debug debug
+ System.out.println("exception while storing " + descriptor.getUrl() + " : " + e.getClass().getName() + " " + e.getMessage());
+ }
+
+ return new Object[] { new Integer(bytes.length), recordId};
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.source.ContentSource#store(de.enough.polish.content.ContentDescriptor, java.lang.Object)
+ */
protected synchronized Object store(ContentDescriptor descriptor, Object data) throws IOException {
// Do nothing here as the #storeContentAndGetDataSize method will be used. instead
return null;
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.source.ContentSource#load(de.enough.polish.content.ContentDescriptor)
+ */
protected synchronized Object load(ContentDescriptor descriptor)
throws IOException {
// do nothing here as it is a storage
return null;
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.source.ContentSource#load(de.enough.polish.content.storage.StorageReference)
+ */
protected synchronized Object load(StorageReference reference) throws IOException {
try {
// get the record id
View
102 enough-polish-j2me/source/src/de/enough/polish/content/source/impl/RmsStorageIndex.java
@@ -19,32 +19,99 @@
import de.enough.polish.io.Serializer;
import de.enough.polish.util.ArrayList;
+/**
+ * Defines a Storage Index using the RMS for persistence
+ * @author Ovidiu Iliescu
+ */
public class RmsStorageIndex extends StorageIndex {
+
+ /**
+ * The default record store name to use
+ */
static final String STORAGE = "RMSStorageIndex";
+
+ /**
+ * Indicates that the index of the actual record containing the StorageIndex is not known
+ */
static final int RECORD_UNKNOWN = Integer.MIN_VALUE;
+ /**
+ * The record store holding the index
+ */
RecordStore store;
+
+ /**
+ * The actual recordID of the record holding the index
+ */
int recordId = RECORD_UNKNOWN;
- public RmsStorageIndex(int maxCacheSize) {
+ public RmsStorageIndex(long maxCacheSize) {
+ this(STORAGE,maxCacheSize);
+ }
+
+ /**
+ * Creates a new RmsStorageIndex instance
+ * @param recordStoreName the name of the record store to use for persisting the index
+ * @param maxCacheSize the maximum size of the index
+ */
+ public RmsStorageIndex(String recordStoreName, long maxCacheSize) {
super(maxCacheSize);
- try {
- // open the record store
- this.store = RecordStore.openRecordStore(STORAGE, true);
- RecordEnumeration recordEnumeration = this.store.enumerateRecords(
- null, null, false);
-
- if (recordEnumeration.hasNextElement()) {
- this.recordId = recordEnumeration.nextRecordId();
+ // When using a dedicated store, use fail-safe behavior
+ if ( STORAGE.equals(recordStoreName) ) {
+ try {
+ // open the record store
+ this.store = RecordStore.openRecordStore(recordStoreName, true);
+ RecordEnumeration recordEnumeration = this.store.enumerateRecords(
+ null, null, false);
+
+ if (recordEnumeration.hasNextElement()) {
+ this.recordId = recordEnumeration.nextRecordId();
+
+ //#debug debug
+ System.out.println("index record id : " + this.recordId);
+ }
- //#debug debug
- System.out.println("index record id : " + this.recordId);
+ } catch (RecordStoreException e) {
+ //#debug error
+ System.out.println("unable to open record store " + e);
}
+ } else {
+ // When using a custom store, make sure the index is always stored in the first record
+ this.recordId = 1;
- } catch (RecordStoreException e) {
- //#debug error
- System.out.println("unable to open record store " + e);
+ // Initialize the first record
+ try {
+ // open the record store
+ this.store = RecordStore.openRecordStore(recordStoreName, true);
+
+ // see if the first record exists. if it does, we're done
+ store.getRecord(1);
+ } catch (InvalidRecordIDException e) {
+ // If it doesn't exist, reserve a spot for it and serialize an empty index at that location
+ try {
+ this.store.addRecord(new byte[1], 0, 1);
+ store(this.index);
+ } catch (Exception e2) {
+ //#debug error
+ System.out.println("unable to initialize index " + e);
+ }
+ } catch (RecordStoreException e) {
+ //#debug error
+ System.out.println("unable to open record store " + e);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.storage.StorageIndex#getAvailableCacheSize()
+ */
+ public long getAvailableCacheSize() {
+ try {
+ long available = Math.min(this.maxCacheSize - getCacheSize(), store.getSizeAvailable() - getCacheSize());
+ return available;
+ } catch (RecordStoreNotOpenException e) {
+ return this.maxCacheSize;
}
}
@@ -100,8 +167,8 @@ protected void store(ArrayList index) {
store.setRecord(this.recordId, bytes, 0, bytes.length);
}
else
- {
- // add the record
+ {
+ // Create the record
this.recordId = store.addRecord(bytes,0,bytes.length);
}
} catch (IOException e) {
@@ -113,6 +180,9 @@ protected void store(ArrayList index) {
}
}
+ /* (non-Javadoc)
+ * @see de.enough.polish.content.storage.StorageIndex#shutdown()
+ */
public void shutdown() {
super.shutdown();
View
31 enough-polish-j2me/source/src/de/enough/polish/content/storage/StorageIndex.java
@@ -27,7 +27,7 @@
/**
* the maximum cache size
*/
- final long maxCacheSize;
+ protected final long maxCacheSize;
/**
* is the StorageIndex prepared ?
@@ -167,6 +167,15 @@ public int size() {
public long getCacheSize() {
return this.cacheSize;
}
+
+ /**
+ * Returns the maximum possible number of bytes that can be stored. This takes into consideration both user-specified limitations
+ * (e.g. maximum cache size) and platform-specific limitations (e.g. storage space).
+ * @return the maximum possible number of bytes that can be stored in the cache.
+ */
+ public long getAvailableCacheSize() {
+ return maxCacheSize - cacheSize;
+ }
/**
* Loads the ArrayList representing the index. It is encouraged to overwrite
@@ -207,7 +216,7 @@ public StorageReference getReference(ContentDescriptor descriptor) {
return null;
}
-
+
/**
* Returns true, if the current cache size is greater than the threshold,
* otherwise false
@@ -216,7 +225,21 @@ public StorageReference getReference(ContentDescriptor descriptor) {
* otherwise false
*/
public boolean isCleanNeeded() {
- return getCacheSize() > this.maxCacheSize;
+ return isCleanNeeded(0);
+ }
+
+ /**
+ * Returns true, if the current cache size is not enough to store an additional extraBytes bytes,
+ * otherwise false
+ *
+ * @param extraBytes the number of extra bytes to store
+ * @return true, if the current cache size is greater than the threshold,
+ * otherwise false
+ */
+ public boolean isCleanNeeded(int extraBytes) {
+ int OVERHEAD = 256;
+ long finalSize = extraBytes + OVERHEAD;
+ return finalSize > getAvailableCacheSize();
}
/*
@@ -252,7 +275,7 @@ public int compare(Object first, Object second) {
*/
public boolean isDisposableTo(StorageReference reference,
StorageReference master) {
- return reference.getPriority() <= master.getPriority() && reference.getCreationTime() < master.getCreationTime();
+ return reference.getPriority() <= master.getPriority() && reference.getLastActivityTime() < master.getLastActivityTime();
}
/**
Something went wrong with that request. Please try again.